From 913472df2cca73056a3ccc70833e6e2963cc7c83 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Thu, 29 Mar 2018 09:42:58 +0200 Subject: [PATCH] Bug 794693 - Crash when trying to view email message source --- src/e-util/e-search-bar.c | 2 + src/e-util/e-web-view.c | 5 +- src/mail/e-mail-browser.c | 11 +++ src/mail/e-mail-paned-view.c | 4 ++ src/mail/e-mail-reader.c | 96 +++++++++++++++++++++++---- src/mail/e-mail-reader.h | 1 + src/modules/mail/e-mail-shell-content.c | 38 +++++++++++ src/modules/settings/e-settings-mail-reader.c | 2 + 8 files changed, 145 insertions(+), 14 deletions(-) diff --git a/src/e-util/e-search-bar.c b/src/e-util/e-search-bar.c index 2b5a86038b..3c0a86d6bc 100644 --- a/src/e-util/e-search-bar.c +++ b/src/e-util/e-search-bar.c @@ -360,6 +360,8 @@ search_bar_dispose (GObject *object) priv = E_SEARCH_BAR_GET_PRIVATE (object); if (priv->web_view != NULL) { + g_signal_handlers_disconnect_by_data (priv->web_view, object); + g_object_unref (priv->web_view); priv->web_view = NULL; } diff --git a/src/e-util/e-web-view.c b/src/e-util/e-web-view.c index af0dfd37e7..679a91f536 100644 --- a/src/e-util/e-web-view.c +++ b/src/e-util/e-web-view.c @@ -1982,6 +1982,7 @@ web_view_can_execute_editing_command_cb (WebKitWebView *webkit_web_view, webkit_web_view, result, NULL); gtk_action_set_sensitive (action, can_do_command); + g_object_unref (action); } static void @@ -2008,7 +2009,7 @@ web_view_selectable_update_actions (ESelectable *selectable, WEBKIT_EDITING_COMMAND_CUT, NULL, /* cancellable */ (GAsyncReadyCallback) web_view_can_execute_editing_command_cb, - action); + g_object_ref (action)); gtk_action_set_tooltip (action, _("Cut the selection")); action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); @@ -2017,7 +2018,7 @@ web_view_selectable_update_actions (ESelectable *selectable, WEBKIT_EDITING_COMMAND_PASTE, NULL, /* cancellable */ (GAsyncReadyCallback) web_view_can_execute_editing_command_cb, - action); + g_object_ref (action)); gtk_action_set_tooltip (action, _("Paste the clipboard")); action = e_focus_tracker_get_select_all_action (focus_tracker); diff --git a/src/mail/e-mail-browser.c b/src/mail/e-mail-browser.c index de246c442c..5c7dba866d 100644 --- a/src/mail/e-mail-browser.c +++ b/src/mail/e-mail-browser.c @@ -581,6 +581,8 @@ mail_browser_dispose (GObject *object) priv = E_MAIL_BROWSER_GET_PRIVATE (object); + e_mail_reader_dispose (E_MAIL_READER (object)); + if (priv->close_on_reply_response_handler_id > 0) { g_signal_handler_disconnect ( priv->close_on_reply_alert, @@ -846,6 +848,9 @@ mail_browser_get_mail_display (EMailReader *reader) EWebView *web_view; preview_pane = e_mail_reader_get_preview_pane (reader); + if (!preview_pane) + return NULL; + web_view = e_preview_pane_get_web_view (preview_pane); return E_MAIL_DISPLAY (web_view); @@ -870,6 +875,9 @@ mail_browser_get_popup_menu (EMailReader *reader) browser = E_MAIL_BROWSER (reader); ui_manager = e_mail_browser_get_ui_manager (browser); + if (!ui_manager) + return NULL; + widget = gtk_ui_manager_get_widget (ui_manager, "/mail-preview-popup"); return GTK_MENU (widget); @@ -882,6 +890,9 @@ mail_browser_get_preview_pane (EMailReader *reader) priv = E_MAIL_BROWSER_GET_PRIVATE (reader); + if (!priv->preview_pane) + return NULL; + return E_PREVIEW_PANE (priv->preview_pane); } diff --git a/src/mail/e-mail-paned-view.c b/src/mail/e-mail-paned-view.c index 7918adf541..bdd197cd71 100644 --- a/src/mail/e-mail-paned-view.c +++ b/src/mail/e-mail-paned-view.c @@ -433,6 +433,8 @@ mail_paned_view_dispose (GObject *object) priv = E_MAIL_PANED_VIEW_GET_PRIVATE (object); + e_mail_reader_dispose (E_MAIL_READER (object)); + if (priv->paned != NULL) { g_object_unref (priv->paned); priv->paned = NULL; @@ -458,6 +460,8 @@ mail_paned_view_dispose (GObject *object) priv->view_instance = NULL; } + priv->display = NULL; + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_mail_paned_view_parent_class)->dispose (object); } diff --git a/src/mail/e-mail-reader.c b/src/mail/e-mail-reader.c index 75d1de343d..429e1e951f 100644 --- a/src/mail/e-mail-reader.c +++ b/src/mail/e-mail-reader.c @@ -99,6 +99,8 @@ struct _EMailReaderPrivate { gpointer remote_content_alert; /* EAlert */ gpointer followup_alert; /* weak pointer to an EAlert */ + + GSList *ongoing_operations; /* GCancellable * */ }; enum { @@ -150,7 +152,7 @@ mail_reader_private_free (EMailReaderPrivate *priv) if (priv->retrieving_message != NULL) { g_cancellable_cancel (priv->retrieving_message); g_object_unref (priv->retrieving_message); - priv->retrieving_message = 0; + priv->retrieving_message = NULL; } g_slice_free (EMailReaderPrivate, priv); @@ -1918,15 +1920,17 @@ mail_source_retrieved (GObject *source_object, closure->message_uid, message, CAMEL_FOLDER (source_object)); g_object_unref (message); - } else { - gchar *status; - - status = g_strdup_printf ( - "%s
%s", - _("Failed to retrieve message:"), - error->message); - e_mail_display_set_status (display, status); - g_free (status); + } else if (error) { + if (display) { + gchar *status; + + status = g_strdup_printf ( + "%s
%s", + _("Failed to retrieve message:"), + error->message); + e_mail_display_set_status (display, status); + g_free (status); + } g_error_free (error); } @@ -1973,7 +1977,7 @@ action_mail_show_source_cb (GtkAction *action, e_mail_display_set_status (display, string); gtk_widget_show (browser); - activity = e_mail_reader_new_activity (reader); + activity = e_mail_reader_new_activity (E_MAIL_READER (browser)); e_activity_set_text (activity, string); cancellable = e_activity_get_cancellable (activity); g_free (string); @@ -3633,7 +3637,6 @@ set_mail_display_part_list (GObject *object, GError *local_error = NULL; reader = E_MAIL_READER (object); - display = e_mail_reader_get_mail_display (reader); part_list = e_mail_reader_parse_message_finish (reader, result, &local_error); @@ -3644,6 +3647,8 @@ set_mail_display_part_list (GObject *object, return; } + display = e_mail_reader_get_mail_display (reader); + e_mail_display_set_part_list (display, part_list); e_mail_display_load (display, NULL); @@ -3671,6 +3676,9 @@ mail_reader_set_display_formatter_for_message (EMailReader *reader, g_free (mail_uri); if (parts == NULL) { + if (!priv->retrieving_message) + priv->retrieving_message = camel_operation_new (); + e_mail_reader_parse_message ( reader, folder, message_uid, message, priv->retrieving_message, @@ -4656,6 +4664,63 @@ connect_signals: G_CALLBACK (e_mail_reader_changed), reader); } +static void +mail_reader_ongoing_operation_destroyed (gpointer user_data, + GObject *cancellable) +{ + EMailReader *reader = user_data; + EMailReaderPrivate *priv; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + priv = E_MAIL_READER_GET_PRIVATE (reader); + + priv->ongoing_operations = g_slist_remove (priv->ongoing_operations, cancellable); +} + +void +e_mail_reader_dispose (EMailReader *reader) +{ + EMailReaderPrivate *priv; + EMailDisplay *mail_display; + GtkWidget *message_list; + GSList *ongoing_operations, *link; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + priv = E_MAIL_READER_GET_PRIVATE (reader); + + if (priv->message_selected_timeout_id > 0) { + g_source_remove (priv->message_selected_timeout_id); + priv->message_selected_timeout_id = 0; + } + + if (priv->retrieving_message) + g_cancellable_cancel (priv->retrieving_message); + + ongoing_operations = g_slist_copy_deep (priv->ongoing_operations, (GCopyFunc) g_object_ref, NULL); + g_slist_free (priv->ongoing_operations); + priv->ongoing_operations = NULL; + + for (link = ongoing_operations; link; link = g_slist_next (link)) { + GCancellable *cancellable = link->data; + + g_object_weak_unref (G_OBJECT (cancellable), mail_reader_ongoing_operation_destroyed, reader); + + g_cancellable_cancel (cancellable); + } + + g_slist_free_full (ongoing_operations, g_object_unref); + + mail_display = e_mail_reader_get_mail_display (reader); + if (mail_display) + g_signal_handlers_disconnect_by_data (mail_display, reader); + + message_list = e_mail_reader_get_message_list (reader); + if (message_list) + g_signal_handlers_disconnect_by_data (message_list, reader); +} + void e_mail_reader_changed (EMailReader *reader) { @@ -4884,6 +4949,7 @@ e_mail_reader_check_state (EMailReader *reader) EActivity * e_mail_reader_new_activity (EMailReader *reader) { + EMailReaderPrivate *priv; EActivity *activity; EMailBackend *backend; EAlertSink *alert_sink; @@ -4891,12 +4957,18 @@ e_mail_reader_new_activity (EMailReader *reader) g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); + priv = E_MAIL_READER_GET_PRIVATE (reader); + activity = e_activity_new (); alert_sink = e_mail_reader_get_alert_sink (reader); e_activity_set_alert_sink (activity, alert_sink); cancellable = camel_operation_new (); + + priv->ongoing_operations = g_slist_prepend (priv->ongoing_operations, cancellable); + g_object_weak_ref (G_OBJECT (cancellable), mail_reader_ongoing_operation_destroyed, reader); + e_activity_set_cancellable (activity, cancellable); g_object_unref (cancellable); diff --git a/src/mail/e-mail-reader.h b/src/mail/e-mail-reader.h index 63c2f12e3a..e1878b6acd 100644 --- a/src/mail/e-mail-reader.h +++ b/src/mail/e-mail-reader.h @@ -142,6 +142,7 @@ GType e_mail_reader_get_type (void); void e_mail_reader_init (EMailReader *reader, gboolean init_actions, gboolean connect_signals); +void e_mail_reader_dispose (EMailReader *reader); void e_mail_reader_changed (EMailReader *reader); guint32 e_mail_reader_check_state (EMailReader *reader); EActivity * e_mail_reader_new_activity (EMailReader *reader); diff --git a/src/modules/mail/e-mail-shell-content.c b/src/modules/mail/e-mail-shell-content.c index c8d6a677ae..e12a05e1b4 100644 --- a/src/modules/mail/e-mail-shell-content.c +++ b/src/modules/mail/e-mail-shell-content.c @@ -244,6 +244,10 @@ mail_shell_content_dispose (GObject *object) priv->mail_view = NULL; } + /* Intentionally after freeing the mail_view, because + the widgets it contains/references can be freed already */ + e_mail_reader_dispose (E_MAIL_READER (object)); + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_mail_shell_content_parent_class)->dispose (object); } @@ -362,6 +366,9 @@ mail_shell_content_check_state (EShellContent *shell_content) mail_shell_content = E_MAIL_SHELL_CONTENT (shell_content); + if (!mail_shell_content->priv->mail_view) + return 0; + /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ reader = E_MAIL_READER (mail_shell_content->priv->mail_view); @@ -378,6 +385,9 @@ mail_shell_content_focus_search_results (EShellContent *shell_content) mail_shell_content = E_MAIL_SHELL_CONTENT (shell_content); + if (!mail_shell_content->priv->mail_view) + return; + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); message_list = e_mail_reader_get_message_list (reader); @@ -394,6 +404,9 @@ mail_shell_content_open_selected_mail (EMailReader *reader) mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + if (!mail_shell_content->priv->mail_view) + return 0; + /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ reader = E_MAIL_READER (mail_shell_content->priv->mail_view); @@ -435,6 +448,9 @@ mail_shell_content_get_backend (EMailReader *reader) mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + if (!mail_shell_content->priv->mail_view) + return NULL; + /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ reader = E_MAIL_READER (mail_shell_content->priv->mail_view); @@ -449,9 +465,13 @@ mail_shell_content_get_mail_display (EMailReader *reader) mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + if (!mail_shell_content->priv->mail_view) + return NULL; + /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ reader = E_MAIL_READER (mail_shell_content->priv->mail_view); + return e_mail_reader_get_mail_display (reader); } @@ -462,6 +482,9 @@ mail_shell_content_get_hide_deleted (EMailReader *reader) mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + if (!mail_shell_content->priv->mail_view) + return FALSE; + /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ reader = E_MAIL_READER (mail_shell_content->priv->mail_view); @@ -476,6 +499,9 @@ mail_shell_content_get_message_list (EMailReader *reader) mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + if (!mail_shell_content->priv->mail_view) + return NULL; + /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ reader = E_MAIL_READER (mail_shell_content->priv->mail_view); @@ -490,6 +516,9 @@ mail_shell_content_get_popup_menu (EMailReader *reader) mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + if (!mail_shell_content->priv->mail_view) + return NULL; + /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ reader = E_MAIL_READER (mail_shell_content->priv->mail_view); @@ -504,6 +533,9 @@ mail_shell_content_get_preview_pane (EMailReader *reader) mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + if (!mail_shell_content->priv->mail_view) + return NULL; + /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ reader = E_MAIL_READER (mail_shell_content->priv->mail_view); @@ -518,6 +550,9 @@ mail_shell_content_get_window (EMailReader *reader) mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + if (!mail_shell_content->priv->mail_view) + return NULL; + /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ reader = E_MAIL_READER (mail_shell_content->priv->mail_view); @@ -533,6 +568,9 @@ mail_shell_content_set_folder (EMailReader *reader, mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + if (!mail_shell_content->priv->mail_view) + return; + /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ reader = E_MAIL_READER (mail_shell_content->priv->mail_view); diff --git a/src/modules/settings/e-settings-mail-reader.c b/src/modules/settings/e-settings-mail-reader.c index 780a181318..bb1cf71050 100644 --- a/src/modules/settings/e-settings-mail-reader.c +++ b/src/modules/settings/e-settings-mail-reader.c @@ -46,6 +46,8 @@ settings_mail_reader_idle_cb (EExtension *extension) EShell *shell; extensible = e_extension_get_extensible (extension); + if (!extensible) + return FALSE; settings = e_util_ref_settings ("org.gnome.evolution.mail"); -- 2.11.4.GIT