[evolution/webkit: 80/96] Port http data cache.



commit e1f8a728009a48c4a12e556d585adf76bb2ff15d
Author: Dan VrÃtil <dvratil redhat com>
Date:   Thu Dec 15 11:29:52 2011 +0100

    Port http data cache.
    
    EMFormatHTML used to have cache for external resources requested
    via http protocol. Since EMFormat does not take care of these things
    anymore, I moved the cache to EMailDisplay, which holds EWebViews
    who do the http requests automatically, thus managing the cache from
    there makes more sense.

 mail/e-mail-display.c         |  156 +++++++++++++++++++++++++++++++++-------
 mail/em-format-html-display.c |   29 +++++---
 mail/em-format-html.c         |   30 +--------
 mail/em-format-html.h         |    4 -
 4 files changed, 148 insertions(+), 71 deletions(-)
---
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index aca8265..fcefaed 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -38,6 +38,8 @@
 #include "mail/e-mail-attachment-bar.h"
 #include "widgets/misc/e-attachment-button.h"
 
+#include <camel/camel.h>
+
 #include <libsoup/soup.h>
 #include <libsoup/soup-requester.h>
 
@@ -70,6 +72,8 @@ enum {
 
 static gpointer parent_class;
 
+static CamelDataCache *emd_global_http_cache = 0;
+
 typedef void (*WebViewActionFunc) (EWebView *web_view);
 
 static const gchar *ui =
@@ -358,6 +362,96 @@ mail_display_link_clicked (WebKitWebView *web_view,
 }
 
 static void
+webkit_request_load_from_file (WebKitNetworkRequest *request,
+			       const gchar *path)
+{
+	gchar *data = NULL;
+	gsize length = 0;
+	gboolean status;
+	gchar *b64, *new_uri;
+	gchar *ct;
+
+	status = g_file_get_contents (path, &data, &length, NULL);
+	if (!status)
+		return;
+
+	b64 = g_base64_encode ((guchar*) data, length);
+	ct = g_content_type_guess (path, NULL, 0, NULL);
+
+	new_uri =  g_strdup_printf ("data:%s;base64,%s", ct, b64);
+	webkit_network_request_set_uri (request, new_uri);
+
+	g_free (b64);
+	g_free (new_uri);
+	g_free (ct);
+	g_free (data);
+}
+
+static void
+add_resource_to_cache (WebKitWebResource *resource)
+{
+
+	/* Make sure this URI is not yet in cache */
+	if (!camel_data_cache_get (emd_global_http_cache, "http",
+		webkit_web_resource_get_uri (resource), NULL)) {
+
+		CamelStream *stream;
+		GString *data;
+		gssize len = 0;
+
+		/* Create cache item */
+		stream = camel_data_cache_add (emd_global_http_cache, "http",
+			webkit_web_resource_get_uri (resource), NULL);
+		if (!stream)
+			return;
+
+		/* Write content of the resource to the cache */
+		data = webkit_web_resource_get_data (resource);
+		len = camel_stream_write_string (stream, data->str, NULL, NULL);
+
+		/* Don't store invalid data in cache */
+		if (len != data->len) {
+			camel_data_cache_remove (emd_global_http_cache, "http",
+				webkit_web_resource_get_uri (resource), NULL);
+		}
+	}
+}
+
+static void
+mail_display_webkit_finished (GObject *object,
+			      GParamSpec *pspec,
+			      gpointer user_data)
+{
+	WebKitLoadStatus status;
+	WebKitWebView *web_view;
+	WebKitWebFrame *frame;
+	WebKitWebDataSource *data_source;
+	WebKitWebResource *subresource;
+	GList *iter, *subresources;
+
+	/* Wait until all resources in webview are fully downloaded. */
+	g_object_get (object, "load-status", &status, NULL);
+	if (status != WEBKIT_LOAD_FINISHED)
+		return;
+
+	web_view = WEBKIT_WEB_VIEW (object);
+	frame = webkit_web_view_get_main_frame (web_view);
+	data_source = webkit_web_frame_get_data_source (frame);
+
+	/* Store in cache the main resource, content of the frame itself */
+	subresource = webkit_web_data_source_get_main_resource (data_source);
+	add_resource_to_cache (subresource);
+
+	/* Store all subresources (images, subframes, ...) */
+	subresources = webkit_web_data_source_get_subresources (data_source);
+	for (iter = subresources; iter; iter = iter->next) {
+		subresource = iter->data;
+		add_resource_to_cache (subresource);
+	}
+}
+
+
+static void
 mail_display_resource_requested (WebKitWebView *web_view,
 				 WebKitWebFrame *frame,
 				 WebKitWebResource *resource,
@@ -371,7 +465,7 @@ mail_display_resource_requested (WebKitWebView *web_view,
 
         /* Redirect cid:part_id to mail://mail_id/cid:part_id */
         if (g_str_has_prefix (uri, "cid:")) {
-		gchar *new_uri = em_format_build_mail_uri (EM_FORMAT (formatter)->folder, 
+		gchar *new_uri = em_format_build_mail_uri (EM_FORMAT (formatter)->folder,
 			EM_FORMAT (formatter)->message_uid,
 			"part_id", G_TYPE_STRING, uri, NULL);
 
@@ -382,33 +476,28 @@ mail_display_resource_requested (WebKitWebView *web_view,
         /* WebKit won't allow to load a local file when displaing "remote" mail://,
            protocol, so we need to handle this manually */
         } else if (g_str_has_prefix (uri, "file:")) {
-                gchar *data = NULL;
-                gsize length = 0;
-                gboolean status;
-                gchar *path;
-
-                path = g_filename_from_uri (uri, NULL, NULL);
-                if (!path)
-                        return;
-
-		status = g_file_get_contents (path, &data, &length, NULL);
-                if (status) {
-                        gchar *b64, *new_uri;
-                        gchar *ct;
-
-                        b64 = g_base64_encode ((guchar*) data, length);
-                        ct = g_content_type_guess (path, NULL, 0, NULL);
-
-                        new_uri =  g_strdup_printf ("data:%s;base64,%s", ct, b64);
-                        webkit_network_request_set_uri (request, new_uri);
-
-                        g_free (b64);
-                        g_free (new_uri);
-                        g_free (ct);
-                }
-                g_free (data);
-                g_free (path);
-        }
+		gchar *path;
+
+		path = g_filename_from_uri (uri, NULL, NULL);
+		if (!path)
+			return;
+
+		webkit_request_load_from_file (request, path);
+
+		g_free (path);
+
+		/* Try to lookup content of any http(s) request in camel cache. */
+        } else if (g_str_has_prefix (uri, "http:") || g_str_has_prefix (uri, "https")) {
+
+		gchar *path = camel_data_cache_get_filename (emd_global_http_cache,
+			"http", uri, NULL);
+
+		/* Found cache file, load the request from cache. */
+		if (path) {
+			webkit_request_load_from_file (request, path);
+			g_free (path);
+		}
+	}
 }
 
 static void
@@ -455,6 +544,8 @@ mail_display_setup_webview (EMailDisplay *display)
 		G_CALLBACK (mail_display_resource_requested), display);
 	g_signal_connect (web_view, "process-mailto",
 		G_CALLBACK (mail_display_process_mailto), display);
+	g_signal_connect (web_view, "notify::load-status",
+		G_CALLBACK (mail_display_webkit_finished), NULL);
 
 	/* EWebView's action groups are added during its instance
 	 * initialization function (like what we're in now), so it
@@ -786,6 +877,7 @@ mail_display_init (EMailDisplay *display)
 {
 	SoupSession *session;
 	SoupSessionFeature *feature;
+	const gchar *user_cache_dir;
 
 	display->priv = E_MAIL_DISPLAY_GET_PRIVATE (display);
 
@@ -804,6 +896,14 @@ mail_display_init (EMailDisplay *display)
 	soup_session_feature_add_feature (feature, E_TYPE_MAIL_REQUEST);
 	soup_session_add_feature (session, feature);
 	g_object_unref (feature);
+
+	/* cache expiry - 2 hour access, 1 day max */
+	user_cache_dir = e_get_user_cache_dir ();
+	emd_global_http_cache = camel_data_cache_new (user_cache_dir, NULL);
+	if (emd_global_http_cache) {
+		camel_data_cache_set_expire_age (emd_global_http_cache, 24*60*60);
+		camel_data_cache_set_expire_access (emd_global_http_cache, 2*60*60);
+	}
 }
 
 GType
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index 2642593..1a1fe75 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -692,12 +692,18 @@ action_image_save_cb (GtkAction *action,
 	} else {
 		CamelStream *image_stream;
 		CamelDataWrapper *dw;
+		CamelDataCache *cache;
 		const gchar *filename;
-
-		image_stream = em_format_html_get_cached_image (
-			EM_FORMAT_HTML (efhd), image_src);
-		if (!image_stream)
+		const gchar *user_cache_dir;
+
+		/* Open cache and find the file there */
+		user_cache_dir = e_get_user_cache_dir ();
+		cache = camel_data_cache_new (user_cache_dir, NULL);
+		image_stream = camel_data_cache_get (cache, "http", image_src, NULL);
+		if (!image_stream) {
+			g_object_unref (cache);
 			return;
+		}
 
 		filename = strrchr (image_src, '/');
 		if (filename && strchr (filename, '?'))
@@ -721,6 +727,7 @@ action_image_save_cb (GtkAction *action,
 			part, CAMEL_TRANSFER_ENCODING_BASE64);
 
 		g_object_unref (image_stream);
+		g_object_unref (cache);
 	}
 
 	file = e_shell_run_save_dialog (
@@ -756,14 +763,20 @@ efhd_web_view_update_actions_cb (EWebView *web_view,
 	image_src = e_web_view_get_cursor_image_src (web_view);
 	visible = image_src && g_str_has_prefix (image_src, "cid:");
 	if (!visible && image_src) {
+		CamelDataCache *cache;
 		CamelStream *image_stream;
+		const gchar *user_cache_dir;
+
+		user_cache_dir = e_get_user_cache_dir ();
+		cache = camel_data_cache_new (user_cache_dir, NULL);
+		image_stream = camel_data_cache_get (cache, "http", image_src, NULL);
 
-		image_stream = em_format_html_get_cached_image (
-			EM_FORMAT_HTML (efhd), image_src);
 		visible = image_stream != NULL;
 
 		if (image_stream)
 			g_object_unref (image_stream);
+
+		g_object_unref (cache);
 	}
 
 	action = e_web_view_get_action (web_view, "efhd-image-save");
@@ -997,8 +1010,6 @@ efhd_attachment_button (EMFormat *emf,
 			GCancellable *cancellable)
 {
 	EMFormatAttachmentPURI *info = (EMFormatAttachmentPURI *) puri;
-	EMFormatHTML *efh = (EMFormatHTML *) emf;
-	EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) efh;
 	GtkWidget *widget;
 
 	/* FIXME: handle default shown case */
@@ -1026,7 +1037,6 @@ efhd_attachment_bar (EMFormat *emf,
 		     EMFormatPURI *puri,
 		     GCancellable *cancellable)
 {
-	EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay*) emf;
 	EMFormatAttachmentBarPURI *abp = (EMFormatAttachmentBarPURI *) puri;
 	GtkWidget *widget;
 
@@ -1075,7 +1085,6 @@ efhd_message_add_bar (EMFormat *emf,
                       EMFormatParserInfo *info,
                       GCancellable *cancellable)
 {
-	gchar *classid;
 	EMFormatAttachmentBarPURI *puri;
 	gint len;
 
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index d124f36..8a3bd7c 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -1422,16 +1422,7 @@ efh_class_init (EMFormatHTMLClass *class)
 			GDK_TYPE_COLOR,
 			G_PARAM_READWRITE));
 
-	/* cache expiry - 2 hour access, 1 day max */
-
-	/* FIXME WEBKIT - this emfh_http_cache is not used anywhere - remove?
-	user_cache_dir = e_get_user_cache_dir ();
-	emfh_http_cache = camel_data_cache_new (user_cache_dir, NULL);
-	if (emfh_http_cache) {
-		camel_data_cache_set_expire_age (emfh_http_cache, 24*60*60);
-		camel_data_cache_set_expire_access (emfh_http_cache, 2*60*60);
-	}
-	*/
+
 }
 
 static void
@@ -2489,22 +2480,3 @@ efh_format_full_headers (EMFormatHTML *efh,
 
 	g_string_append (buffer, "</tr></table>");
 }
-
-
-/* unref returned pointer with g_object_unref(), if not NULL */
-CamelStream *
-em_format_html_get_cached_image (EMFormatHTML *efh,
-                                 const gchar *image_uri)
-{
-	g_return_val_if_fail (efh != NULL, NULL);
-	g_return_val_if_fail (image_uri != NULL, NULL);
-
-	/* FIXME WEBKIT This has not been ported yet
-	if (!emfh_http_cache)
-		return NULL;
-
-	return camel_data_cache_get (
-		emfh_http_cache, EMFH_HTTP_CACHE_PATH, image_uri, NULL);
-	*/
-	return NULL;
-}
diff --git a/mail/em-format-html.h b/mail/em-format-html.h
index 1e49f64..bea595f 100644
--- a/mail/em-format-html.h
+++ b/mail/em-format-html.h
@@ -184,10 +184,6 @@ CamelMimePart *	em_format_html_file_part	(EMFormatHTML *efh,
 gchar *		em_format_html_format_cert_infos
 						(CamelCipherCertInfo *first_cinfo);
 
-CamelStream *
-		em_format_html_get_cached_image	(EMFormatHTML *efh,
-						 const gchar *image_uri);
-
 void		em_format_html_format_message	(EMFormatHTML *efh,
 						 CamelStream *stream,
 						 GCancellable *cancellable);



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