aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Vrátil <dvratil@redhat.com>2012-06-14 18:01:41 +0800
committerDan Vrátil <dvratil@redhat.com>2012-06-14 18:14:45 +0800
commit4f47f662f6daa7b9a3daed77d66b2022ae8398ab (patch)
tree24fe8456d16c4c42145771780c575f9ca9c7c126
parent50ad565a15f4e630c06f78dddc6b3d00ea7ee34a (diff)
downloadgsoc2013-evolution-4f47f662f6daa7b9a3daed77d66b2022ae8398ab.tar.gz
gsoc2013-evolution-4f47f662f6daa7b9a3daed77d66b2022ae8398ab.tar.zst
gsoc2013-evolution-4f47f662f6daa7b9a3daed77d66b2022ae8398ab.zip
Bug #674887 - Hang on sender's photo lookup
-rw-r--r--em-format/e-mail-formatter-headers.c38
-rw-r--r--em-format/e-mail-parser-headers.c26
-rw-r--r--libemail-engine/e-mail-utils.c44
-rw-r--r--libemail-engine/e-mail-utils.h3
-rw-r--r--mail/e-mail-display.c11
-rw-r--r--mail/e-mail-request.c125
6 files changed, 181 insertions, 66 deletions
diff --git a/em-format/e-mail-formatter-headers.c b/em-format/e-mail-formatter-headers.c
index 24d27139b5..8971adf897 100644
--- a/em-format/e-mail-formatter-headers.c
+++ b/em-format/e-mail-formatter-headers.c
@@ -248,9 +248,6 @@ format_full_headers (EMailFormatter *formatter,
struct _camel_header_raw *header;
gboolean have_icon = FALSE;
const gchar *photo_name = NULL;
- CamelInternetAddress *cia = NULL;
- EShell *shell;
- ESourceRegistry *registry;
gboolean face_decoded = FALSE, contact_has_photo = FALSE;
guchar *face_header_value = NULL;
gsize face_header_len = 0;
@@ -262,9 +259,6 @@ format_full_headers (EMailFormatter *formatter,
if (g_cancellable_is_cancelled (cancellable))
return;
- shell = e_shell_get_default ();
- registry = e_shell_get_registry (shell);
-
ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
charset = camel_content_type_param (ct, "charset");
charset = camel_iconv_charset_name (charset);
@@ -327,7 +321,7 @@ format_full_headers (EMailFormatter *formatter,
g_string_append (
buffer,
- "<tr><td><table border=1 width=\"100%%\" "
+ "<tr valign=\"top\"><td><table border=1 width=\"100%%\" "
"cellspacing=2 cellpadding=2><tr>");
if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
g_string_append (
@@ -352,7 +346,10 @@ format_full_headers (EMailFormatter *formatter,
g_free (header_sender);
g_free (header_from);
- g_string_append (buffer, "<tr><td width=\"100%%\"><table border=0 cellpadding=\"0\">\n");
+ g_string_append (
+ buffer,
+ "<tr valign=\"top\"><td width=\"100%%\">"
+ "<table border=0 cellpadding=\"0\">\n");
g_free (evolution_imagesdir);
@@ -446,22 +443,20 @@ format_full_headers (EMailFormatter *formatter,
g_string_append (buffer, "</table></td>");
if (photo_name) {
- CamelMimePart *photopart;
gboolean only_local_photo;
+ gchar *name;
- cia = camel_internet_address_new ();
- camel_address_decode ((CamelAddress *) cia, (const gchar *) photo_name);
+ name = g_uri_escape_string (photo_name, NULL, FALSE);
only_local_photo = e_mail_formatter_get_only_local_photos (formatter);
- photopart = em_utils_contact_photo (
- registry, cia, only_local_photo);
+ g_string_append (buffer, "<td align=\"right\" valign=\"top\">");
- if (photopart) {
- g_string_append (buffer, "<td align=\"right\" valign=\"top\">");
- write_contact_picture (photopart, -1, buffer);
- g_string_append (buffer, "</td>");
- g_object_unref (photopart);
- }
- g_object_unref (cia);
+ g_string_append_printf (buffer,
+ "<img src=\"mail://contact-photo?mailaddr=&only-local-photo=1\" "
+ "data-mailaddr=\"%s\" %s id=\"__evo-contact-photo\"/>",
+ name, only_local_photo ? "data-onlylocal=1" : "");
+ g_string_append (buffer, "</td>");
+
+ g_free (name);
}
if (!contact_has_photo && face_decoded) {
@@ -536,10 +531,11 @@ emfe_headers_format (EMailFormatterExtension *extension,
g_string_append_printf (
buffer,
- "<div class=\"headers\" style=\"background: #%06x;\">"
+ "<div class=\"headers\" style=\"background: #%06x;\" id=\"%s\">"
"<table border=\"0\" width=\"100%%\" style=\"color: #%06x;\">\n"
"<tr><td valign=\"top\" width=\"16\">\n",
bg_color,
+ part->id,
e_color_to_value ((GdkColor *)
e_mail_formatter_get_color (
formatter,
diff --git a/em-format/e-mail-parser-headers.c b/em-format/e-mail-parser-headers.c
index 06f28746f0..0a2c2bd40e 100644
--- a/em-format/e-mail-parser-headers.c
+++ b/em-format/e-mail-parser-headers.c
@@ -58,6 +58,31 @@ G_DEFINE_TYPE_EXTENDED (
static const gchar *parser_mime_types[] = { "application/vnd.evolution.headers", NULL };
+static void
+empe_headers_bind_dom (EMailPart *part,
+ WebKitDOMElement *element)
+{
+ WebKitDOMDocument *document;
+ WebKitDOMElement *photo;
+ gchar *addr, *uri;
+ gboolean only_local;
+
+ document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
+ photo = webkit_dom_document_get_element_by_id (document, "__evo-contact-photo");
+
+ addr = webkit_dom_element_get_attribute (photo, "data-mailaddr");
+ only_local = webkit_dom_element_has_attribute (photo, "data-onlylocal");
+
+ uri = g_strdup_printf ("mail://contact-photo?mailaddr=%s%s",
+ addr, only_local ? "&only-local-photo=1" : "");
+
+ webkit_dom_html_image_element_set_src (
+ WEBKIT_DOM_HTML_IMAGE_ELEMENT (photo), uri);
+
+ g_free (addr);
+ g_free (uri);
+}
+
static GSList *
empe_headers_parse (EMailParserExtension *extension,
EMailParser *parser,
@@ -76,6 +101,7 @@ empe_headers_parse (EMailParserExtension *extension,
mail_part = e_mail_part_new (part, part_id->str);
mail_part->mime_type = g_strdup ("application/vnd.evolution.headers");
+ mail_part->bind_func = empe_headers_bind_dom;
g_string_truncate (part_id, len);
return g_slist_append (NULL, mail_part);
diff --git a/libemail-engine/e-mail-utils.c b/libemail-engine/e-mail-utils.c
index 9e13a74aa8..7fca5eb306 100644
--- a/libemail-engine/e-mail-utils.c
+++ b/libemail-engine/e-mail-utils.c
@@ -278,26 +278,6 @@ em_utils_folder_is_outbox (ESourceRegistry *registry,
/* ********************************************************************** */
-static void
-emu_addr_cancel_stop (gpointer data)
-{
- gboolean *stop = data;
-
- g_return_if_fail (stop != NULL);
-
- *stop = TRUE;
-}
-
-static void
-emu_addr_cancel_cancellable (gpointer data)
-{
- GCancellable *cancellable = data;
-
- g_return_if_fail (cancellable != NULL);
-
- g_cancellable_cancel (cancellable);
-}
-
struct TryOpenEBookStruct {
GError **error;
EFlag *flag;
@@ -399,7 +379,8 @@ search_address_in_addressbooks (ESourceRegistry *registry,
gboolean local_only,
gboolean (*check_contact) (EContact *contact,
gpointer user_data),
- gpointer user_data)
+ gpointer user_data,
+ GCancellable *cancellable)
{
GList *list, *link;
GList *addr_sources = NULL;
@@ -408,8 +389,6 @@ search_address_in_addressbooks (ESourceRegistry *registry,
gpointer ptr;
EBookQuery *book_query;
gchar *query;
- GHook *hook_cancellable;
- GCancellable *cancellable;
const gchar *extension_name;
if (!address || !*address)
@@ -474,15 +453,10 @@ search_address_in_addressbooks (ESourceRegistry *registry,
g_list_free_full (list, (GDestroyNotify) g_object_unref);
- cancellable = g_cancellable_new ();
- hook_cancellable = mail_cancel_hook_add (
- emu_addr_cancel_cancellable, cancellable);
-
for (link = addr_sources; !stop && !found && link != NULL; link = g_list_next (link)) {
ESource *source = E_SOURCE (link->data);
GSList *contacts;
EBookClient *book_client = NULL;
- GHook *hook_stop;
gboolean cached_book = FALSE;
const gchar *display_name;
const gchar *uid;
@@ -500,8 +474,6 @@ search_address_in_addressbooks (ESourceRegistry *registry,
d(printf(" checking '%s'\n", e_source_get_uri(source)));
- hook_stop = mail_cancel_hook_add (emu_addr_cancel_stop, &stop);
-
book_client = g_hash_table_lookup (emu_books_hash, uid);
if (!book_client) {
book_client = e_book_client_new (source, &err);
@@ -601,8 +573,6 @@ search_address_in_addressbooks (ESourceRegistry *registry,
g_clear_error (&err);
}
- mail_cancel_hook_remove (hook_stop);
-
if (stop && !cached_book && book_client) {
g_object_unref (book_client);
} else if (!stop && book_client && !cached_book) {
@@ -611,9 +581,6 @@ search_address_in_addressbooks (ESourceRegistry *registry,
}
}
- mail_cancel_hook_remove (hook_cancellable);
- g_object_unref (cancellable);
-
g_list_free_full (addr_sources, (GDestroyNotify) g_object_unref);
g_free (query);
@@ -644,7 +611,7 @@ em_utils_in_addressbook (ESourceRegistry *registry,
return FALSE;
return search_address_in_addressbooks (
- registry, addr, local_only, NULL, NULL);
+ registry, addr, local_only, NULL, NULL, NULL);
}
static gboolean
@@ -687,7 +654,8 @@ static GSList *photos_cache = NULL; /* list of PhotoInfo-s */
CamelMimePart *
em_utils_contact_photo (ESourceRegistry *registry,
CamelInternetAddress *cia,
- gboolean local_only)
+ gboolean local_only,
+ GCancellable *cancellable)
{
const gchar *addr = NULL;
CamelMimePart *part = NULL;
@@ -723,7 +691,7 @@ em_utils_contact_photo (ESourceRegistry *registry,
/* !p means the address had not been found in the cache */
if (!p && search_address_in_addressbooks (
- registry, addr, local_only, extract_photo_data, &photo)) {
+ registry, addr, local_only, extract_photo_data, &photo, cancellable)) {
PhotoInfo *pi;
diff --git a/libemail-engine/e-mail-utils.h b/libemail-engine/e-mail-utils.h
index 505249a0ac..8898204ef1 100644
--- a/libemail-engine/e-mail-utils.h
+++ b/libemail-engine/e-mail-utils.h
@@ -38,7 +38,8 @@ gboolean em_utils_in_addressbook (ESourceRegistry *registry,
gboolean local_only);
CamelMimePart * em_utils_contact_photo (ESourceRegistry *registry,
CamelInternetAddress *addr,
- gboolean local);
+ gboolean local,
+ GCancellable *cancellable);
ESource * em_utils_guess_mail_account (ESourceRegistry *registry,
CamelMimeMessage *message,
CamelFolder *folder);
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index 33922d8c0a..1ca8bcc8a9 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -1048,6 +1048,7 @@ toggle_headers_visibility (WebKitDOMElement *button,
WebKitDOMCSSStyleDeclaration *css_short, *css_full;
gboolean expanded;
const gchar *path;
+ gchar *css_value;
document = webkit_web_view_get_dom_document (web_view);
@@ -1064,9 +1065,10 @@ toggle_headers_visibility (WebKitDOMElement *button,
return;
css_full = webkit_dom_element_get_style (full_headers);
-
- expanded = (g_strcmp0 (webkit_dom_css_style_declaration_get_property_value (
- css_full, "display"), "block") == 0);
+ css_value = webkit_dom_css_style_declaration_get_property_value (
+ css_full, "display");
+ expanded = (g_strcmp0 (css_value, "block") == 0);
+ g_free (css_value);
webkit_dom_css_style_declaration_set_property (css_full, "display",
expanded ? "none" : "block", "", NULL);
@@ -1233,6 +1235,9 @@ mail_parts_bind_dom (GObject *object,
return;
frame_name = webkit_web_frame_get_name (frame);
+ if (!frame_name || !*frame_name)
+ frame_name = ".message.headers";
+
for (iter = display->priv->part_list->list; iter; iter = iter->next) {
EMailPart *part = iter->data;
diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c
index 01c114405d..5805a10b26 100644
--- a/mail/e-mail-request.c
+++ b/mail/e-mail-request.c
@@ -19,6 +19,7 @@
#define LIBSOUP_USE_UNSTABLE_REQUEST_API
#include "e-mail-request.h"
+#include "em-utils.h"
#include <libsoup/soup.h>
#include <libsoup/soup-requester.h>
@@ -36,6 +37,8 @@
#include <e-util/e-icon-factory.h>
#include <e-util/e-util.h>
+#include <shell/e-shell.h>
+
#define d(x)
#define dd(x)
@@ -164,6 +167,116 @@ handle_mail_request (GSimpleAsyncResult *res,
g_simple_async_result_set_op_res_gpointer (res, stream, NULL);
}
+static GInputStream *
+get_empty_image_stream (gsize *len)
+{
+ GdkPixbuf *p;
+ gchar *buff;
+ GInputStream *stream;
+
+ p = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
+ gdk_pixbuf_fill (p, 0x00000000); /* transparent black */
+ gdk_pixbuf_save_to_buffer (p, &buff, len, "png", NULL, NULL);
+
+ stream = g_memory_input_stream_new_from_data (buff, *len, g_free);
+
+ g_object_unref (p);
+
+ return stream;
+}
+
+static void
+handle_contact_photo_request (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ EMailRequest *request = E_MAIL_REQUEST (object);
+ const gchar *email;
+ gchar *photo_name;
+ gboolean only_local_photo;
+ CamelMimePart *photopart;
+ EShell *shell;
+ ESourceRegistry *registry;
+ CamelInternetAddress *cia;
+ CamelDataWrapper *dw;
+ GByteArray *ba;
+ GInputStream *stream = NULL;
+
+ shell = e_shell_get_default ();
+ registry = e_shell_get_registry (shell);
+
+ request->priv->mime_type = g_strdup ("image/*");
+
+ email = g_hash_table_lookup (
+ request->priv->uri_query, "mailaddr");
+ if (!email || !*email) {
+ gsize len;
+
+ stream = get_empty_image_stream (&len);
+ request->priv->content_length = len;
+
+ g_simple_async_result_set_op_res_gpointer (res, stream, NULL);
+ return;
+ }
+
+ photo_name = g_uri_unescape_string (email, NULL);
+ only_local_photo = g_hash_table_lookup_extended (
+ request->priv->uri_query, "only-local-photo",
+ NULL, NULL);
+
+ cia = camel_internet_address_new ();
+ camel_address_decode ((CamelAddress *) cia, (const gchar *) photo_name);
+ photopart = em_utils_contact_photo (
+ registry, cia, only_local_photo, cancellable);
+ if (!photopart) {
+ gsize len;
+
+ stream = get_empty_image_stream (&len);
+ request->priv->content_length = len;
+
+ g_simple_async_result_set_op_res_gpointer (res, stream, NULL);
+ g_free (photo_name);
+ return;
+ }
+
+ ba = NULL;
+ dw = camel_medium_get_content (CAMEL_MEDIUM (photopart));
+ if (dw) {
+ ba = camel_data_wrapper_get_byte_array (dw);
+ }
+
+ if (!ba || ba->len == 0) {
+
+ const gchar *filename = camel_mime_part_get_filename (photopart);
+
+ if (filename && *filename &&
+ g_file_test (filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+ gchar *data;
+ gsize len;
+
+ if (!g_file_get_contents (filename, &data, &len, NULL)) {
+ stream = get_empty_image_stream (&len);
+ } else {
+ stream = g_memory_input_stream_new_from_data (
+ (gchar *) data, len, g_free);
+ }
+
+ request->priv->content_length = len;
+ }
+
+ } else {
+
+ stream = g_memory_input_stream_new_from_data (
+ (gchar *) ba->data, ba->len, NULL);
+
+ request->priv->content_length = ba->len;
+
+ }
+
+ g_free (photo_name);
+ g_simple_async_result_set_op_res_gpointer (res, stream, NULL);
+}
+
static void
mail_request_finalize (GObject *object)
{
@@ -233,9 +346,15 @@ mail_request_send_async (SoupRequest *request,
g_simple_async_result_set_check_cancellable (simple, cancellable);
- g_simple_async_result_run_in_thread (
- simple, handle_mail_request,
- G_PRIORITY_DEFAULT, cancellable);
+ if (g_strcmp0 (uri->host, "contact-photo") == 0) {
+ g_simple_async_result_run_in_thread (
+ simple, handle_contact_photo_request,
+ G_PRIORITY_DEFAULT, cancellable);
+ } else {
+ g_simple_async_result_run_in_thread (
+ simple, handle_mail_request,
+ G_PRIORITY_DEFAULT, cancellable);
+ }
g_object_unref (simple);
}