[evolution] Bug #677608 - Fails to open message which is not yet downloaded
- From: Dan VrÃtil <dvratil src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Bug #677608 - Fails to open message which is not yet downloaded
- Date: Mon, 18 Jun 2012 12:00:06 +0000 (UTC)
commit fe59b10f04b794759f64d97281d907d7dce39972
Author: Dan VrÃtil <dvratil redhat com>
Date: Mon Jun 18 13:44:58 2012 +0200
Bug #677608 - Fails to open message which is not yet downloaded
em-format/e-mail-part-list.c | 54 ++++++++++
em-format/e-mail-part-list.h | 13 ++-
mail/e-http-request.c | 24 ++---
mail/e-mail-reader-utils.c | 237 ++++++++++++++++++++----------------------
mail/e-mail-reader-utils.h | 14 +--
mail/e-mail-reader.c | 21 +++-
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 743834b..0ad8a91 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 12a24f3..d0c2055 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 f5fd12f..3bc4878 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 2030350..0f0d68e 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 a3a1cdb..7118f01 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 069f064..c350b52 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 544f5f3..ec17a84 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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]