From 91822b42dc7b5eb64cad2626f9fc620a2ee6a2c8 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 5 Dec 2012 08:19:04 -0500 Subject: Make EMailPartList thread-safe. Exposing data members in the public struct is unwise, especially when EMailPartList is used from multiple threads. Instead keep the members private and provide a set of thread-safe functions to manipulate them. --- mail/e-http-request.c | 6 ++-- mail/e-mail-display.c | 73 ++++++++++++++++++++++++++-------------------- mail/e-mail-printer.c | 16 +++++++--- mail/e-mail-reader-utils.c | 18 ++++++++---- mail/e-mail-reader.c | 14 ++++++--- mail/e-mail-request.c | 5 ++-- mail/em-utils.c | 20 ++++++++----- 7 files changed, 95 insertions(+), 57 deletions(-) (limited to 'mail') diff --git a/mail/e-http-request.c b/mail/e-http-request.c index 4b77950a4c..5c4b638ac8 100644 --- a/mail/e-http-request.c +++ b/mail/e-http-request.c @@ -291,12 +291,14 @@ handle_http_request (GSimpleAsyncResult *res, EShell *shell; ESourceRegistry *registry; CamelInternetAddress *addr; + CamelMimeMessage *message; shell = e_shell_get_default (); registry = e_shell_get_registry (shell); - addr = camel_mime_message_get_from (part_list->message); + message = e_mail_part_list_get_message (part_list); + addr = camel_mime_message_get_from (message); force_load_images = em_utils_in_addressbook ( - registry, addr, FALSE, cancellable); + registry, addr, FALSE, cancellable); g_object_unref (part_list); } diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c index 9cbc9832eb..4f706eef10 100644 --- a/mail/e-mail-display.c +++ b/mail/e-mail-display.c @@ -246,12 +246,14 @@ mail_display_process_mailto (EWebView *web_view, if (g_ascii_strncasecmp (mailto_uri, "mailto:", 7) == 0) { EShell *shell; EMailPartList *part_list; + CamelFolder *folder; part_list = E_MAIL_DISPLAY (web_view)->priv->part_list; + folder = e_mail_part_list_get_folder (part_list); shell = e_shell_get_default (); em_utils_compose_new_message_with_mailto ( - shell, mailto_uri, part_list->folder); + shell, mailto_uri, folder); return TRUE; } @@ -347,11 +349,16 @@ 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:")) { + CamelFolder *folder; + const gchar *message_uid; gchar *new_uri; + folder = e_mail_part_list_get_folder (part_list); + message_uid = e_mail_part_list_get_message_uid (part_list); + /* Always write raw content of CID object. */ new_uri = e_mail_part_build_uri ( - part_list->folder, part_list->message_uid, + folder, message_uid, "part_id", G_TYPE_STRING, uri, "mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_RAW, NULL); @@ -376,6 +383,8 @@ mail_display_resource_requested (WebKitWebView *web_view, * See EMailRequest for further details about this. */ } else if (g_str_has_prefix (uri, "http:") || g_str_has_prefix (uri, "https:") || g_str_has_prefix (uri, "evo-http:") || g_str_has_prefix (uri, "evo-https:")) { + CamelFolder *folder; + const gchar *message_uid; gchar *new_uri, *mail_uri, *enc; SoupURI *soup_uri; GHashTable *query; @@ -396,10 +405,12 @@ mail_display_resource_requested (WebKitWebView *web_view, return; } + folder = e_mail_part_list_get_folder (part_list); + message_uid = e_mail_part_list_get_message_uid (part_list); + new_uri = g_strconcat ("evo-", uri, NULL); mail_uri = e_mail_part_build_uri ( - part_list->folder, - part_list->message_uid, NULL, NULL); + folder, message_uid, NULL, NULL); soup_uri = soup_uri_new (new_uri); if (soup_uri->query) @@ -766,8 +777,8 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view, EMailFormatterExtension *extension; GQueue *extensions; GList *iter; - EMailPart *part; - GtkWidget *widget; + EMailPart *part = NULL; + GtkWidget *widget = NULL; gchar *part_id, *type, *object_uri; part_id = g_hash_table_lookup (param, "data"); @@ -787,14 +798,14 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view, } /* Find the EMailPart representing the requested widget. */ - part = e_mail_part_list_find_part (display->priv->part_list, part_id); + part = e_mail_part_list_ref_part (display->priv->part_list, part_id); if (part == NULL) return NULL; reg = e_mail_formatter_get_extension_registry (display->priv->formatter); extensions = e_mail_extension_registry_get_for_mime_type (reg, type); if (extensions == NULL) - return NULL; + goto exit; extension = NULL; for (iter = g_queue_peek_head_link (extensions); iter; iter = iter->next) { @@ -808,7 +819,7 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view, } if (extension == NULL) - return NULL; + goto exit; /* Get the widget from formatter */ widget = e_mail_formatter_extension_get_widget ( @@ -820,7 +831,7 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view, /* Should not happen! WebKit will display an ugly 'Plug-in not * available' placeholder instead of hiding the element. */ if (widget == NULL) - return NULL; + goto exit; /* Attachment button has URI different then the actual PURI because * that URI identifies the attachment itself */ @@ -966,6 +977,10 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view, display->priv->widgets, g_strdup (object_uri), g_object_ref (widget)); +exit: + if (part != NULL) + e_mail_part_unref (part); + return widget; } @@ -1153,7 +1168,8 @@ mail_parts_bind_dom (GObject *object, WebKitWebView *web_view; WebKitDOMDocument *document; EMailDisplay *display; - GSList *iter; + GQueue queue = G_QUEUE_INIT; + GList *head, *link; const gchar *frame_name; frame = WEBKIT_WEB_FRAME (object); @@ -1171,25 +1187,14 @@ mail_parts_bind_dom (GObject *object, if (frame_name == NULL || *frame_name == '\0') frame_name = ".message.headers"; - for (iter = display->priv->part_list->list; iter; iter = iter->next) { - - EMailPart *part = iter->data; - - if (part == NULL) - continue; - - if (g_strcmp0 (part->id, frame_name) == 0) - break; - } - document = webkit_web_view_get_dom_document (web_view); - while (iter != NULL) { - EMailPart *part = iter->data; - if (part == NULL) { - iter = iter->next; - continue; - } + e_mail_part_list_queue_parts ( + display->priv->part_list, frame_name, &queue); + head = g_queue_peek_head_link (&queue); + + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *part = link->data; /* Iterate only the parts rendered in * the frame and all it's subparts. */ @@ -1205,9 +1210,10 @@ mail_parts_bind_dom (GObject *object, part->bind_func (part, element); } } - - iter = iter->next; } + + while (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); } static void @@ -1787,6 +1793,8 @@ e_mail_display_load (EMailDisplay *display, const gchar *msg_uri) { EMailPartList *part_list; + CamelFolder *folder; + const gchar *message_uid; gchar *uri; g_return_if_fail (E_IS_MAIL_DISPLAY (display)); @@ -1799,8 +1807,11 @@ e_mail_display_load (EMailDisplay *display, return; } + folder = e_mail_part_list_get_folder (part_list); + message_uid = e_mail_part_list_get_message_uid (part_list); + uri = e_mail_part_build_uri ( - part_list->folder, part_list->message_uid, + folder, message_uid, "mode", G_TYPE_INT, display->priv->mode, "headers_collapsable", G_TYPE_BOOLEAN, display->priv->headers_collapsable, diff --git a/mail/e-mail-printer.c b/mail/e-mail-printer.c index 92642bb996..30c8517a50 100644 --- a/mail/e-mail-printer.c +++ b/mail/e-mail-printer.c @@ -201,11 +201,17 @@ emp_start_printing (GObject *object, static void emp_run_print_operation (EMailPrinter *emp) { + EMailPartList *part_list; + CamelFolder *folder; + const gchar *message_uid; gchar *mail_uri; + part_list = emp->priv->parts_list; + folder = e_mail_part_list_get_folder (part_list); + message_uid = e_mail_part_list_get_message_uid (part_list); + mail_uri = e_mail_part_build_uri ( - emp->priv->parts_list->folder, - emp->priv->parts_list->message_uid, + folder, message_uid, "__evo-load-image", G_TYPE_BOOLEAN, TRUE, "mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_PRINTING, NULL); @@ -623,6 +629,7 @@ emp_set_parts_list (EMailPrinter *emp, EMailPartList *parts_list) { CamelMediumHeader *header; + CamelMimeMessage *message; GArray *headers; gint i; GtkTreeIter last_known = { 0 }; @@ -637,7 +644,8 @@ emp_set_parts_list (EMailPrinter *emp, 5, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT); - headers = camel_medium_get_headers (CAMEL_MEDIUM (parts_list->message)); + message = e_mail_part_list_get_message (parts_list); + headers = camel_medium_get_headers (CAMEL_MEDIUM (message)); if (!headers) return; @@ -676,7 +684,7 @@ emp_set_parts_list (EMailPrinter *emp, COLUMN_HEADER_STRUCT, emfh, -1); } - camel_medium_free_headers (CAMEL_MEDIUM (parts_list->message), headers); + camel_medium_free_headers (CAMEL_MEDIUM (message), headers); } static void diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c index acece830a1..9f027a65fd 100644 --- a/mail/e-mail-reader-utils.c +++ b/mail/e-mail-reader-utils.c @@ -1268,15 +1268,17 @@ mail_reader_reply_message_parsed (GObject *object, EMailBackend *backend; EMailReader *reader = E_MAIL_READER (object); EMailPartList *part_list; + CamelMimeMessage *message; AsyncContext *context = user_data; part_list = e_mail_reader_parse_message_finish (reader, result); + message = e_mail_part_list_get_message (part_list); backend = e_mail_reader_get_backend (context->reader); shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); em_utils_reply_to_message ( - shell, part_list->message, + shell, message, context->folder, context->message_uid, context->reply_type, context->reply_style, part_list, context->address); @@ -1403,12 +1405,14 @@ e_mail_reader_reply_to_message (EMailReader *reader, if (!part_list) { goto whole_message; } else { - GSList *piter; + GQueue queue = G_QUEUE_INIT; + + e_mail_part_list_queue_parts (part_list, NULL, &queue); - for (piter = part_list->list; piter; piter = piter->next) { - EMailPart *part = piter->data; + while (!g_queue_is_empty (&queue)) { + EMailPart *part = g_queue_pop_head (&queue); - if (part && part->validities) { + if (part->validities) { GSList *viter; for (viter = part->validities; viter; viter = viter->next) { @@ -1422,11 +1426,13 @@ e_mail_reader_reply_to_message (EMailReader *reader, } } } + + e_mail_part_unref (part); } } if (src_message == NULL) { - src_message = part_list->message; + src_message = e_mail_part_list_get_message (part_list); if (src_message != NULL) g_object_ref (src_message); diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c index 923b3d403c..a659404092 100644 --- a/mail/e-mail-reader.c +++ b/mail/e-mail-reader.c @@ -281,6 +281,7 @@ action_mail_image_save_cb (GtkAction *action, EMailPartList *parts; const gchar *image_src; CamelMimePart *part; + CamelMimeMessage *message; EAttachment *attachment; GFile *file; @@ -296,11 +297,13 @@ action_mail_image_save_cb (GtkAction *action, parts = e_mail_display_get_parts_list (display); g_return_if_fail (parts != NULL); - g_return_if_fail (parts->message != NULL); + + message = e_mail_part_list_get_message (parts); + g_return_if_fail (message != NULL); if (g_str_has_prefix (image_src, "cid:")) { part = camel_mime_message_get_part_by_content_id ( - parts->message, image_src + 4); + message, image_src + 4); g_return_if_fail (part != NULL); g_object_ref (part); @@ -2697,7 +2700,7 @@ mail_reader_message_seen_cb (EMailReaderClosure *closure) uid_is_current &= (g_strcmp0 (current_uid, message_uid) == 0); if (parts) - message = parts->message; + message = e_mail_part_list_get_message (parts); else message = NULL; @@ -2869,7 +2872,10 @@ mail_reader_message_selected_timeout_cb (EMailReader *reader) parts = e_mail_display_get_parts_list (display); cursor_uid = MESSAGE_LIST (message_list)->cursor_uid; - format_uid = parts ? parts->message_uid : NULL; + if (parts != NULL) + format_uid = e_mail_part_list_get_message_uid (parts); + else + format_uid = NULL; if (MESSAGE_LIST (message_list)->last_sel_single) { GtkWidget *widget; diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c index b07b5f0c49..665711f927 100644 --- a/mail/e-mail-request.c +++ b/mail/e-mail-request.c @@ -116,7 +116,7 @@ handle_mail_request (GSimpleAsyncResult *res, const gchar *mime_type; /* original part_id is owned by the GHashTable */ part_id = soup_uri_decode (part_id); - part = e_mail_part_list_find_part (part_list, part_id); + part = e_mail_part_list_ref_part (part_list, part_id); val = g_hash_table_lookup (request->priv->uri_query, "mime_type"); if (val) { @@ -129,10 +129,11 @@ handle_mail_request (GSimpleAsyncResult *res, mime_type = "application/vnd.evolution.source"; } - if (part) { + if (part != NULL) { e_mail_formatter_format_as ( formatter, &context, part, request->priv->output_stream, mime_type ? mime_type : part->mime_type, cancellable); + e_mail_part_unref (part); } else { g_warning ("Failed to lookup requested part '%s' - this should not happen!", part_id); } diff --git a/mail/em-utils.c b/mail/em-utils.c index 923b11f9c4..d533be741d 100644 --- a/mail/em-utils.c +++ b/mail/em-utils.c @@ -1229,12 +1229,12 @@ em_utils_get_proxy (void) } static gboolean -is_only_text_part_in_this_level (GSList *parts, +is_only_text_part_in_this_level (GList *parts, EMailPart *text_html_part) { const gchar *dot; gint level_len; - GSList *iter; + GList *iter; g_return_val_if_fail (parts != NULL, FALSE); g_return_val_if_fail (text_html_part != NULL, FALSE); @@ -1297,7 +1297,8 @@ em_utils_message_to_html (CamelSession *session, GtkWindow *window; EMailPart *hidden_text_html_part = NULL; guint32 is_validity_found = 0; - GSList *iter; + GQueue queue = G_QUEUE_INIT; + GList *head, *link; shell = e_shell_get_default (); window = e_shell_get_active_window (shell); @@ -1333,18 +1334,18 @@ em_utils_message_to_html (CamelSession *session, } /* Return all found validities and possibly show hidden prefer-plain part */ - for (iter = parts_list->list; iter; iter = iter->next) { + e_mail_part_list_queue_parts (parts_list, NULL, &queue); + head = g_queue_peek_head_link (&queue); - EMailPart *part = iter->data; - if (!part) - continue; + for (link = head; link != NULL; link = g_list_next (link)) { + EMailPart *part = link->data; /* prefer-plain can hide HTML parts, even when it's the only * text part in the email, thus show it (and hide again later) */ if (part->is_hidden && !hidden_text_html_part && part->mime_type && !part->is_attachment && g_ascii_strcasecmp (part->mime_type, "text/html") == 0 && - is_only_text_part_in_this_level (parts_list->list, part)) { + is_only_text_part_in_this_level (head, part)) { part->is_hidden = FALSE; hidden_text_html_part = part; } @@ -1361,6 +1362,9 @@ em_utils_message_to_html (CamelSession *session, } } + while (!g_queue_is_empty (&queue)) + e_mail_part_unref (g_queue_pop_head (&queue)); + if (validity_found) *validity_found = is_validity_found; -- cgit v1.2.3