diff options
author | Dan Vrátil <dvratil@redhat.com> | 2012-06-14 18:01:41 +0800 |
---|---|---|
committer | Dan Vrátil <dvratil@redhat.com> | 2012-06-14 18:14:45 +0800 |
commit | 4f47f662f6daa7b9a3daed77d66b2022ae8398ab (patch) | |
tree | 24fe8456d16c4c42145771780c575f9ca9c7c126 | |
parent | 50ad565a15f4e630c06f78dddc6b3d00ea7ee34a (diff) | |
download | gsoc2013-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.c | 38 | ||||
-rw-r--r-- | em-format/e-mail-parser-headers.c | 26 | ||||
-rw-r--r-- | libemail-engine/e-mail-utils.c | 44 | ||||
-rw-r--r-- | libemail-engine/e-mail-utils.h | 3 | ||||
-rw-r--r-- | mail/e-mail-display.c | 11 | ||||
-rw-r--r-- | mail/e-mail-request.c | 125 |
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); } |