[evolution] Bug 794693 - Crash when trying to view email message source



commit 913472df2cca73056a3ccc70833e6e2963cc7c83
Author: Milan Crha <mcrha redhat com>
Date:   Thu Mar 29 09:42:58 2018 +0200

    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 2b5a860..3c0a86d 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 af0dfd3..679a91f 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 de246c4..5c7dba8 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 7918adf..bdd197c 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 75d1de3..429e1e9 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<br>%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<br>%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 63c2f12..e1878b6 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 c8d6a67..e12a05e 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 780a181..bb1cf71 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");
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]