diff options
-rw-r--r-- | em-format/e-mail-part-list.c | 54 | ||||
-rw-r--r-- | em-format/e-mail-part-list.h | 13 | ||||
-rw-r--r-- | mail/e-http-request.c | 24 | ||||
-rw-r--r-- | mail/e-mail-reader-utils.c | 237 | ||||
-rw-r--r-- | mail/e-mail-reader-utils.h | 14 | ||||
-rw-r--r-- | mail/e-mail-reader.c | 21 | ||||
-rw-r--r-- | mail/e-mail-request.c | 10 |
7 files changed, 210 insertions, 163 deletions
diff --git a/em-format/e-mail-part-list.c b/em-format/e-mail-part-list.c index 743834beef..0ad8a9198f 100644 --- a/em-format/e-mail-part-list.c +++ b/em-format/e-mail-part-list.c @@ -22,6 +22,10 @@ G_DEFINE_TYPE (EMailPartList, e_mail_part_list, G_TYPE_OBJECT) + +static CamelObjectBag *registry = NULL; +G_LOCK_DEFINE_STATIC (registry); + static void unref_mail_part (gpointer user_data) { @@ -128,3 +132,53 @@ e_mail_part_list_get_iter (GSList *list, return NULL; } + +/** + * e_mail_part_list_get_registry: + * + * Returns a #CamelObjectBag where parsed #EMailPartLists can be stored. + */ +CamelObjectBag * +e_mail_part_list_get_registry (void) +{ + G_LOCK (registry); + if (registry == NULL) { + registry = camel_object_bag_new ( + g_str_hash, g_str_equal, + (CamelCopyFunc) g_strdup, g_free); + } + G_UNLOCK (registry); + + return registry; +} + +static void +part_list_weak_ref_notify (gchar *mail_uri, + EMailPartList *part_list) +{ + CamelObjectBag *reg = e_mail_part_list_get_registry (); + + camel_object_bag_remove (reg, part_list); +} + +/** + * e_mail_part_list_registry_add: + * + * This method should be used to add a new @part_list to the + * #CamelObjectBag registry. It will automatically handle removing + * the @part_list from the bag when it's destroyed. + * + * The @registry don't take any reference to the @part_list. + */ +void +e_mail_part_list_registry_add (CamelObjectBag *registry, + const gchar *mail_uri, + EMailPartList *part_list) +{ + camel_object_bag_add (registry, mail_uri, part_list); + + g_object_weak_ref ( + G_OBJECT (part_list), + (GWeakNotify) part_list_weak_ref_notify, + g_strdup (mail_uri)); +}
\ No newline at end of file diff --git a/em-format/e-mail-part-list.h b/em-format/e-mail-part-list.h index 12a24f365f..d0c2055b31 100644 --- a/em-format/e-mail-part-list.h +++ b/em-format/e-mail-part-list.h @@ -61,16 +61,23 @@ struct _EMailPartListClass { GObjectClass parent_class; }; -EMailPartList * e_mail_part_list_new (); +EMailPartList * e_mail_part_list_new (void); -GType e_mail_part_list_get_type (); +GType e_mail_part_list_get_type (void); EMailPart * e_mail_part_list_find_part (EMailPartList *part_list, const gchar *id); -GSList * e_mail_part_list_get_iter (GSList *list, +GSList * e_mail_part_list_get_iter (GSList *list, const gchar *id); +CamelObjectBag * + e_mail_part_list_get_registry (void); + +void e_mail_part_list_registry_add (CamelObjectBag *registry, + const gchar *mail_uri, + EMailPartList *part_list); + G_END_DECLS #endif /* E_MAIL_PART_LIST_H_ */ diff --git a/mail/e-http-request.c b/mail/e-http-request.c index f5fd12fe40..3bc4878a45 100644 --- a/mail/e-http-request.c +++ b/mail/e-http-request.c @@ -321,16 +321,14 @@ handle_http_request (GSimpleAsyncResult *res, image_policy = e_mail_formatter_get_image_loading_policy (formatter); if (!force_load_images && mail_uri && (image_policy == E_MAIL_IMAGE_LOADING_POLICY_SOMETIMES)) { - SoupSession *session; - GHashTable *parts; + CamelObjectBag *registry; gchar *decoded_uri; EMailPartList *part_list; - session = webkit_get_default_session (); - parts = g_object_get_data (G_OBJECT (session), "mails"); + registry = e_mail_part_list_get_registry (); decoded_uri = soup_uri_decode (mail_uri); - part_list = g_hash_table_lookup (parts, decoded_uri); + part_list = camel_object_bag_get (registry, decoded_uri); if (part_list) { EShell *shell; ESourceRegistry *registry; @@ -341,6 +339,8 @@ handle_http_request (GSimpleAsyncResult *res, addr = camel_mime_message_get_from (part_list->message); force_load_images = em_utils_in_addressbook ( registry, addr, FALSE, cancellable); + + g_object_unref (part_list); } g_free (decoded_uri); @@ -476,8 +476,8 @@ http_request_send_async (SoupRequest *request, gchar *mail_uri; SoupURI *uri; const gchar *enc; - SoupSession *session; - GHashTable *mails, *query; + CamelObjectBag *registry; + GHashTable *query; ehr = E_HTTP_REQUEST (request); uri = soup_request_get_uri (request); @@ -494,18 +494,12 @@ http_request_send_async (SoupRequest *request, mail_uri = soup_uri_decode (enc); - session = webkit_get_default_session (); - mails = g_object_get_data (G_OBJECT (session), "mails"); - g_return_if_fail (mails != NULL); - - ehr->priv->parts_list = g_hash_table_lookup (mails, mail_uri); + registry = e_mail_part_list_get_registry (); + ehr->priv->parts_list = camel_object_bag_get (registry, mail_uri); g_free (mail_uri); g_return_if_fail (ehr->priv->parts_list); - /* Make sure the formatter lives until we are finished here */ - g_object_ref (ehr->priv->parts_list); - simple = g_simple_async_result_new ( G_OBJECT (request), callback, user_data, http_request_send_async); diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c index 2030350d1b..0f0d68ec9d 100644 --- a/mail/e-mail-reader-utils.c +++ b/mail/e-mail-reader-utils.c @@ -57,8 +57,6 @@ #define d(x) -static GHashTable * mail_reader_get_mail_register (void); - typedef struct _AsyncContext AsyncContext; struct _AsyncContext { @@ -538,12 +536,15 @@ free_message_printing_context (struct _MessagePrintingContext *context) } static void -mail_reader_do_print_message (EMailPartList *part_list, +mail_reader_do_print_message (GObject *object, + GAsyncResult *result, gpointer user_data) { + EMailReader *reader = E_MAIL_READER (object); EActivity *activity; GCancellable *cancellable; EMailPrinter *printer; + EMailPartList *part_list; struct _MessagePrintingContext *context = user_data; activity = e_mail_reader_new_activity (context->reader); @@ -551,6 +552,8 @@ mail_reader_do_print_message (EMailPartList *part_list, e_activity_set_state (activity, E_ACTIVITY_RUNNING); cancellable = e_activity_get_cancellable (activity); + part_list = e_mail_reader_parse_message_finish (reader, result); + printer = e_mail_printer_new (part_list); g_signal_connect (printer, "done", G_CALLBACK (printing_done_cb), activity); @@ -578,17 +581,15 @@ mail_reader_get_message_to_print_ready_cb (GObject *object, e_mail_reader_parse_message ( context->reader, context->folder, context->message_uid, - message, (GFunc) mail_reader_do_print_message, context); + message, mail_reader_do_print_message, context); } void e_mail_reader_print (EMailReader *reader, GtkPrintOperationAction action) { - EMailPartList *parts; struct _MessagePrintingContext *context; MessageList *message_list; - gchar *uri; context = g_new0 (struct _MessagePrintingContext, 1); @@ -596,27 +597,15 @@ e_mail_reader_print (EMailReader *reader, context->reader = g_object_ref (reader); context->message_uid = g_strdup (message_list->cursor_uid); context->folder = g_object_ref (e_mail_reader_get_folder (reader)); + context->activity = e_mail_reader_new_activity (reader); g_return_if_fail (E_IS_MAIL_READER (reader)); - uri = e_mail_part_build_uri ( - context->folder, context->message_uid, NULL, NULL); - parts = e_mail_reader_lookup_part_list (reader, uri); - if (!parts) { - GCancellable *cancellable; - - context->activity = e_mail_reader_new_activity (reader); - cancellable = e_activity_get_cancellable (context->activity); - - camel_folder_get_message ( - context->folder, context->message_uid, - G_PRIORITY_DEFAULT, cancellable, - (GAsyncReadyCallback) mail_reader_get_message_to_print_ready_cb, - context); - - } else { - mail_reader_do_print_message (parts, context); - } + camel_folder_get_message ( + context->folder, context->message_uid, + G_PRIORITY_DEFAULT, e_activity_get_cancellable (context->activity), + (GAsyncReadyCallback) mail_reader_get_message_to_print_ready_cb, + context); } static void @@ -855,13 +844,18 @@ html_contains_nonwhitespace (const gchar *html, } static void -mail_reader_reply_message_parsed (EMailPartList *part_list, +mail_reader_reply_message_parsed (GObject *object, + GAsyncResult *result, gpointer user_data) { EShell *shell; EMailBackend *backend; + EMailReader *reader = E_MAIL_READER (object); + EMailPartList *part_list; AsyncContext *context = user_data; + part_list = e_mail_reader_parse_message_finish (reader, result); + backend = e_mail_reader_get_backend (context->reader); shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); @@ -907,8 +901,7 @@ mail_reader_get_message_ready_cb (CamelFolder *folder, e_mail_reader_parse_message (context->reader, context->folder, context->message_uid, message, - (GFunc) mail_reader_reply_message_parsed, - context); + mail_reader_reply_message_parsed, context); } void @@ -932,7 +925,7 @@ e_mail_reader_reply_to_message (EMailReader *reader, gchar *selection = NULL; gint length; gchar *mail_uri; - GHashTable *mail_register; + CamelObjectBag *registry; /* This handles quoting only selected text in the reply. If * nothing is selected or only whitespace is selected, fall @@ -982,9 +975,9 @@ e_mail_reader_reply_to_message (EMailReader *reader, if (!gtk_widget_get_visible (GTK_WIDGET (web_view))) goto whole_message; - mail_register = mail_reader_get_mail_register (); + registry = e_mail_part_list_get_registry (); mail_uri = e_mail_part_build_uri (folder, uid, NULL, NULL); - part_list = g_hash_table_lookup (mail_register, mail_uri); + part_list = camel_object_bag_get (registry, mail_uri); g_free (mail_uri); if (!part_list) @@ -995,7 +988,11 @@ e_mail_reader_reply_to_message (EMailReader *reader, if (src_message != NULL) g_object_ref (src_message); + g_object_unref (part_list); + g_return_if_fail (src_message != NULL); + } else { + g_object_unref (part_list); } if (!e_web_view_is_selection_active (web_view)) @@ -1535,98 +1532,63 @@ e_mail_reader_header_free (EMailReaderHeader *header) g_free (header); } -static GHashTable * -mail_reader_get_mail_register (void) -{ - SoupSession *session; - GHashTable *mails; - - session = webkit_get_default_session (); - mails = g_object_get_data (G_OBJECT (session), "mails"); - if (!mails) { - mails = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, NULL); - g_object_set_data_full ( - G_OBJECT (session), "mails", mails, - (GDestroyNotify) g_hash_table_destroy); - } - - return mails; -} - -EMailPartList * -e_mail_reader_lookup_part_list (EMailReader *reader, - const gchar *uri) -{ - GHashTable *mails; - - g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); - g_return_val_if_fail (uri && *uri, NULL); - - mails = mail_reader_get_mail_register (); - return g_hash_table_lookup (mails, uri); -} +struct mail_reader_parse_message_run_data_ { + CamelFolder *folder; + CamelMimeMessage *message; + gchar *message_uid; + EActivity *activity; -struct _formatter_weak_ref_closure { - GHashTable *part_lists; - gchar *mail_uri; + EMailPartList *part_list; }; static void -part_list_weak_ref_cb (gchar *mail_uri, - EMailPartList *part_list) +mail_reader_parse_message_run (GSimpleAsyncResult *simple, + GObject *object, + GCancellable *cancellable) { - GHashTable *mails; + EMailReader *reader = E_MAIL_READER (object); + CamelObjectBag *registry; + EMailPartList *part_list; + gchar *mail_uri; + struct mail_reader_parse_message_run_data_ *data; - mails = mail_reader_get_mail_register (); + data = g_object_get_data (G_OBJECT (simple), "evo-data"); - /* When this callback is called, the partslist is being finalized - * so we only remove it from the parts list table. */ - g_hash_table_remove (mails, mail_uri); + registry = e_mail_part_list_get_registry (); - d(printf("Destroying parts list %p (%s)\n", part_list, mail_uri)); + mail_uri = e_mail_part_build_uri ( + data->folder, data->message_uid, NULL, NULL); - g_free (mail_uri); -} + part_list = camel_object_bag_reserve (registry, mail_uri); + if (!part_list) { + EMailBackend *mail_backend; + EMailSession *mail_session; + EMailParser *parser; -struct format_parser_async_closure_ { - EActivity *activity; - gchar *mail_uri; + mail_backend = e_mail_reader_get_backend (reader); + mail_session = e_mail_backend_get_session (mail_backend); - GFunc user_callback; - gpointer user_data; -}; + parser = e_mail_parser_new (CAMEL_SESSION (mail_session)); -static void -format_parser_async_done_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - EMailParser *parser = E_MAIL_PARSER (source); - EMailPartList *part_list; - GHashTable *mails; - struct format_parser_async_closure_ *closure = user_data; - - part_list = e_mail_parser_parse_finish (parser, result, NULL); + part_list = e_mail_parser_parse_sync ( + parser, data->folder, data->message_uid, + data->message, + e_activity_get_cancellable (data->activity)); - /* When no EMailDisplay holds reference to the part list, then - * the list can be destroyed. */ - g_object_weak_ref (G_OBJECT (part_list), - (GWeakNotify) part_list_weak_ref_cb, g_strdup (closure->mail_uri)); + g_object_unref (parser); - mails = mail_reader_get_mail_register (); - g_hash_table_insert (mails, g_strdup (closure->mail_uri), part_list); - d(printf("Registered EMailPartList %s\n", closure->mail_uri)); - - if (closure->user_callback) - closure->user_callback (part_list, closure->user_data); + if (!part_list) { + camel_object_bag_abort (registry, mail_uri); + } else { + e_mail_part_list_registry_add ( + registry, mail_uri, part_list); + g_object_ref (part_list); + } + } - g_object_unref (closure->activity); - g_free (closure->mail_uri); - g_free (closure); + g_free (mail_uri); - g_object_unref (result); - g_object_unref (parser); + data->part_list = part_list; } void @@ -1634,31 +1596,54 @@ e_mail_reader_parse_message (EMailReader *reader, CamelFolder *folder, const gchar *message_uid, CamelMimeMessage *message, - GFunc ready_callback, + GAsyncReadyCallback ready_callback, gpointer user_data) { - EMailParser *parser; - EMailBackend *mail_backend; - EMailSession *mail_session; - gchar *mail_uri; - struct format_parser_async_closure_ *closure; + GSimpleAsyncResult *simple; + struct mail_reader_parse_message_run_data_ *data; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + g_return_if_fail (ready_callback != NULL); + + data = g_new0 (struct mail_reader_parse_message_run_data_, 1); + data->activity = e_mail_reader_new_activity (reader); + e_activity_set_text (data->activity, _("Parsing message")); + data->folder = g_object_ref (folder); + data->message = g_object_ref (message); + data->message_uid = g_strdup (message_uid); + + simple = g_simple_async_result_new ( + G_OBJECT (reader), ready_callback, user_data, + e_mail_reader_parse_message); + g_object_set_data (G_OBJECT (simple), "evo-data", data); + + g_simple_async_result_run_in_thread ( + simple, mail_reader_parse_message_run, + G_PRIORITY_DEFAULT, + e_activity_get_cancellable (data->activity)); + + g_object_unref (simple); +} + +EMailPartList * +e_mail_reader_parse_message_finish (EMailReader *reader, + GAsyncResult *result) +{ + struct mail_reader_parse_message_run_data_ *data; + EMailPartList *part_list; - mail_uri = e_mail_part_build_uri (folder, message_uid, NULL, NULL); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL); - mail_backend = e_mail_reader_get_backend (reader); - mail_session = e_mail_backend_get_session (mail_backend); + data = g_object_get_data (G_OBJECT (result), "evo-data"); + g_return_val_if_fail (data, NULL); - closure = g_new0 (struct format_parser_async_closure_, 1); - parser = e_mail_parser_new (CAMEL_SESSION (mail_session)); + part_list = data->part_list; - closure->activity = e_mail_reader_new_activity (reader); - e_activity_set_text (closure->activity, _("Parsing message")); - closure->mail_uri = mail_uri; - closure->user_callback = ready_callback; - closure->user_data = user_data; + g_clear_object (&data->folder); + g_clear_object (&data->message); + g_clear_object (&data->activity); + g_free (data->message_uid); + g_free (data); - e_mail_parser_parse (parser, folder, message_uid, - message, format_parser_async_done_cb, - e_activity_get_cancellable (closure->activity), - closure); + return part_list; } diff --git a/mail/e-mail-reader-utils.h b/mail/e-mail-reader-utils.h index a3a1cdb86d..7118f0149f 100644 --- a/mail/e-mail-reader-utils.h +++ b/mail/e-mail-reader-utils.h @@ -67,21 +67,19 @@ EMailReaderHeader * gchar * e_mail_reader_header_to_xml (EMailReaderHeader *header); void e_mail_reader_header_free (EMailReaderHeader *header); -EMailPartList * e_mail_reader_lookup_part_list (EMailReader *reader, - const gchar *uri); - -void e_mail_reader_store_part_list (EMailReader *reader, - const gchar *uri, - EMailPartList *part_list); - void e_mail_reader_parse_message (EMailReader *reader, CamelFolder *folder, const gchar *message_uid, CamelMimeMessage *message, - GFunc ready_callback, + GAsyncReadyCallback ready_callback, gpointer user_data); +EMailPartList * + e_mail_reader_parse_message_finish + (EMailReader *reader, + GAsyncResult *result); + G_END_DECLS #endif /* E_MAIL_READER_UTILS_H */ diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c index 069f064953..c350b52dd3 100644 --- a/mail/e-mail-reader.c +++ b/mail/e-mail-reader.c @@ -3110,15 +3110,22 @@ struct format_parser_async_closure_ { }; static void -set_mail_display_part_list (EMailPartList *part_list, +set_mail_display_part_list (GObject *object, + GAsyncResult *result, gpointer user_data) { - EMailDisplay *display = user_data; + EMailPartList *part_list; + EMailReader *reader; + EMailDisplay *display; + + reader = E_MAIL_READER (object); + display = e_mail_reader_get_mail_display (reader); + + part_list = e_mail_reader_parse_message_finish (reader, result); e_mail_display_set_parts_list (display, part_list); e_mail_display_load (display, NULL); - g_object_unref (display); /* Remove the reference added when parts list was created, * so that only owners are EMailDisplays */ g_object_unref (part_list); @@ -3131,23 +3138,25 @@ mail_reader_set_display_formatter_for_message (EMailReader *reader, CamelMimeMessage *message, CamelFolder *folder) { + CamelObjectBag *registry; EMailPartList *parts; gchar *mail_uri; mail_uri = e_mail_part_build_uri (folder, message_uid, NULL, NULL); - parts = e_mail_reader_lookup_part_list (reader, mail_uri); + registry = e_mail_part_list_get_registry (); + parts = camel_object_bag_peek (registry, mail_uri); g_free (mail_uri); if (parts == NULL) { e_mail_reader_parse_message ( reader, folder, message_uid, message, - (GFunc) set_mail_display_part_list, - g_object_ref (display)); + set_mail_display_part_list, NULL); } else { e_mail_display_set_parts_list (display, parts); e_mail_display_load (display, NULL); + g_object_unref (parts); } } diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c index 544f5f3f51..ec17a84c82 100644 --- a/mail/e-mail-request.c +++ b/mail/e-mail-request.c @@ -69,8 +69,7 @@ handle_mail_request (GSimpleAsyncResult *res, GInputStream *stream; EMailFormatter *formatter; EMailPartList *part_list; - SoupSession *session; - GHashTable *mails; + CamelObjectBag *registry; GByteArray *ba; gchar *part_id; gchar *val; @@ -84,9 +83,8 @@ handle_mail_request (GSimpleAsyncResult *res, g_object_unref (request->priv->output_stream); } - session = webkit_get_default_session (); - mails = g_object_get_data (G_OBJECT (session), "mails"); - part_list = g_hash_table_lookup (mails, request->priv->uri_base); + registry = e_mail_part_list_get_registry (); + part_list = camel_object_bag_get (registry, request->priv->uri_base); g_return_if_fail (part_list != NULL); request->priv->output_stream = camel_stream_mem_new (); @@ -162,6 +160,8 @@ handle_mail_request (GSimpleAsyncResult *res, }); } + g_object_unref (part_list); + stream = g_memory_input_stream_new_from_data ( (gchar *) ba->data, ba->len, NULL); g_simple_async_result_set_op_res_gpointer (res, stream, NULL); |