[evolution] The "Reply from preview selection" feature is wrong for multipart messages



commit b14222e7fca56d81aee81e06e2320c7a37c4a890
Author: Tomas Popela <tpopela redhat com>
Date:   Mon Oct 24 14:22:22 2016 +0200

    The "Reply from preview selection" feature is wrong for multipart messages
    
    Introduce e_mail_display_get_selection_content_multipart_sync() that
    will return a current selection with the right mime type (that's
    reflecting whether the plain text part of the HTML one is currently
    displayed).

 src/mail/e-mail-display.c            |   44 ++++++++
 src/mail/e-mail-display.h            |    5 +
 src/mail/e-mail-reader-utils.c       |   17 ++-
 src/web-extensions/e-dom-utils.c     |  182 ++++++++++++++++++++++++++--------
 src/web-extensions/e-dom-utils.h     |    3 +
 src/web-extensions/e-web-extension.c |   31 ++++++-
 6 files changed, 233 insertions(+), 49 deletions(-)
---
diff --git a/src/mail/e-mail-display.c b/src/mail/e-mail-display.c
index 073002f..7e5070b 100644
--- a/src/mail/e-mail-display.c
+++ b/src/mail/e-mail-display.c
@@ -2462,6 +2462,50 @@ e_mail_display_set_status (EMailDisplay *display,
 }
 
 gchar *
+e_mail_display_get_selection_content_multipart_sync (EMailDisplay *display,
+                                                     gboolean *is_html,
+                                                     GCancellable *cancellable,
+                                                     GError **error)
+{
+       GDBusProxy *web_extension;
+
+       g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
+
+       if (!e_web_view_is_selection_active (E_WEB_VIEW (display)))
+               return NULL;
+
+       web_extension = e_web_view_get_web_extension_proxy (E_WEB_VIEW (display));
+       if (web_extension) {
+               GVariant *result;
+
+               result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_full (
+                               web_extension,
+                               "GetSelectionContentMultipart",
+                               g_variant_new (
+                                       "(t)",
+                                       webkit_web_view_get_page_id (
+                                               WEBKIT_WEB_VIEW (display))),
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               cancellable,
+                               error);
+
+               if (result) {
+                       gchar *content = NULL;
+                       gboolean text_html = FALSE;
+
+                       g_variant_get (result, "(sb)", &content, &text_html);
+                       g_variant_unref (result);
+                       if (is_html)
+                               *is_html = text_html;
+                       return content;
+               }
+       }
+
+       return NULL;
+}
+
+gchar *
 e_mail_display_get_selection_plain_text_sync (EMailDisplay *display,
                                               GCancellable *cancellable,
                                               GError **error)
diff --git a/src/mail/e-mail-display.h b/src/mail/e-mail-display.h
index 1a75ba4..e1d6fd9 100644
--- a/src/mail/e-mail-display.h
+++ b/src/mail/e-mail-display.h
@@ -94,6 +94,11 @@ GtkAction *  e_mail_display_get_action       (EMailDisplay *display,
                                                 const gchar *action_name);
 void           e_mail_display_set_status       (EMailDisplay *display,
                                                 const gchar *status);
+gchar *                e_mail_display_get_selection_content_multipart_sync
+                                               (EMailDisplay *display,
+                                                gboolean *is_html,
+                                                GCancellable *cancellable,
+                                                GError **error);
 gchar *                e_mail_display_get_selection_plain_text_sync
                                                (EMailDisplay *display,
                                                 GCancellable *cancellable,
diff --git a/src/mail/e-mail-reader-utils.c b/src/mail/e-mail-reader-utils.c
index e95f743..a996990 100644
--- a/src/mail/e-mail-reader-utils.c
+++ b/src/mail/e-mail-reader-utils.c
@@ -2398,7 +2398,7 @@ e_mail_reader_reply_to_message (EMailReader *reader,
        EMailReplyStyle reply_style;
        EWebView *web_view;
        struct _camel_header_raw *header;
-       gboolean src_is_html = FALSE;
+       gboolean src_is_text_html = FALSE;
        const gchar *uid;
        gchar *selection = NULL;
        gint length;
@@ -2502,12 +2502,17 @@ e_mail_reader_reply_to_message (EMailReader *reader,
                goto whole_message;
 
        content_type = camel_mime_part_get_content_type (CAMEL_MIME_PART (src_message));
-       src_is_html = camel_content_type_is (content_type, "text", "html");
 
-       if (src_is_html)
-               selection = e_web_view_get_selection_content_html_sync (web_view, NULL, NULL);
-       else
+       if (camel_content_type_is (content_type, "text", "plain")) {
                selection = e_mail_display_get_selection_plain_text_sync (display, NULL, NULL);
+               src_is_text_html = TRUE;
+       } else if (camel_content_type_is (content_type, "text", "html")) {
+               selection = e_web_view_get_selection_content_html_sync (E_WEB_VIEW (display), NULL, NULL);
+               src_is_text_html = FALSE;
+       } else if (camel_content_type_is (content_type, "multipart", "*")) {
+               selection = e_mail_display_get_selection_content_multipart_sync (display, &src_is_text_html, 
NULL, NULL);
+       }
+
        if (selection == NULL || *selection == '\0')
                goto whole_message;
 
@@ -2540,7 +2545,7 @@ e_mail_reader_reply_to_message (EMailReader *reader,
                CAMEL_MIME_PART (new_message),
                selection,
                length,
-               src_is_html ? "text/html; charset=utf-8" : "text/plain; charset=utf-8");
+               src_is_text_html ? "text/html; charset=utf-8" : "text/plain; charset=utf-8");
 
        ccd = g_new0 (CreateComposerData, 1);
        ccd->reader = g_object_ref (reader);
diff --git a/src/web-extensions/e-dom-utils.c b/src/web-extensions/e-dom-utils.c
index 4d790ca..0330346 100644
--- a/src/web-extensions/e-dom-utils.c
+++ b/src/web-extensions/e-dom-utils.c
@@ -159,6 +159,36 @@ element_is_in_pre_tag (WebKitDOMNode *node)
 }
 
 static gchar *
+dom_selection_get_content_html (WebKitDOMDOMSelection *dom_selection,
+                                WebKitDOMDocument *content_document)
+{
+       gchar *inner_html;
+       WebKitDOMDocumentFragment *fragment;
+       WebKitDOMNode *node;
+       WebKitDOMElement *element;
+       WebKitDOMRange *range = NULL;
+
+       range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+       fragment = webkit_dom_range_clone_contents (range, NULL);
+       element = webkit_dom_document_create_element (content_document, "DIV", NULL);
+       webkit_dom_node_append_child (
+               WEBKIT_DOM_NODE (element),
+               WEBKIT_DOM_NODE (fragment), NULL);
+
+       inner_html = webkit_dom_element_get_inner_html (element);
+
+       node = webkit_dom_range_get_start_container (range, NULL);
+       if (element_is_in_pre_tag (node)) {
+               gchar *tmp = inner_html;
+               inner_html = g_strconcat ("<pre>", tmp, "</pre>", NULL);
+               g_free (tmp);
+       }
+
+       g_clear_object (&range);
+       return inner_html;
+}
+
+static gchar *
 get_frame_selection_html (WebKitDOMElement *iframe)
 {
        WebKitDOMDocument *content_document;
@@ -177,37 +207,10 @@ get_frame_selection_html (WebKitDOMElement *iframe)
        dom_selection = webkit_dom_dom_window_get_selection (dom_window);
        g_clear_object (&dom_window);
        if (dom_selection && (webkit_dom_dom_selection_get_range_count (dom_selection) > 0)) {
-               WebKitDOMRange *range = NULL;
-               WebKitDOMElement *element;
-               WebKitDOMDocumentFragment *fragment;
-
-               range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-               if (range != NULL) {
-                       gchar *inner_html;
-                       WebKitDOMNode *node;
-
-                       fragment = webkit_dom_range_clone_contents (
-                               range, NULL);
-
-                       element = webkit_dom_document_create_element (
-                               content_document, "DIV", NULL);
-                       webkit_dom_node_append_child (
-                               WEBKIT_DOM_NODE (element),
-                               WEBKIT_DOM_NODE (fragment), NULL);
-
-                       inner_html = webkit_dom_element_get_inner_html (element);
-
-                       node = webkit_dom_range_get_start_container (range, NULL);
-                       if (element_is_in_pre_tag (node)) {
-                               gchar *tmp = inner_html;
-                               inner_html = g_strconcat ("<pre>", tmp, "</pre>", NULL);
-                               g_free (tmp);
-                       }
+               gchar *html = dom_selection_get_content_html (dom_selection, content_document);
+               g_clear_object (&dom_selection);
 
-                       g_clear_object (&range);
-                       g_clear_object (&dom_selection);
-                       return inner_html;
-               }
+               return html;
        }
 
        g_clear_object (&dom_selection);
@@ -216,16 +219,15 @@ get_frame_selection_html (WebKitDOMElement *iframe)
        length = webkit_dom_html_collection_get_length (frames);
        for (ii = 0; ii < length; ii++) {
                WebKitDOMNode *node;
-               gchar *text;
+               gchar *html;
 
                node = webkit_dom_html_collection_item (frames, ii);
 
-               text = get_frame_selection_html (
-                       WEBKIT_DOM_ELEMENT (node));
+               html = get_frame_selection_html (WEBKIT_DOM_ELEMENT (node));
 
-               if (text != NULL) {
+               if (html != NULL) {
                        g_clear_object (&frames);
-                       return text;
+                       return html;
                }
        }
 
@@ -266,6 +268,20 @@ e_dom_utils_get_selection_content_html (WebKitDOMDocument *document)
 }
 
 static gchar *
+dom_selection_get_content_text (WebKitDOMDOMSelection *dom_selection)
+{
+       WebKitDOMRange *range = NULL;
+       gchar *text = NULL;
+
+       range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+       if (range)
+               text = webkit_dom_range_to_string (range, NULL);
+       g_clear_object (&range);
+
+       return text;
+}
+
+static gchar *
 get_frame_selection_content_text (WebKitDOMElement *iframe)
 {
        WebKitDOMDocument *content_document;
@@ -284,13 +300,7 @@ get_frame_selection_content_text (WebKitDOMElement *iframe)
        dom_selection = webkit_dom_dom_window_get_selection (dom_window);
        g_clear_object (&dom_window);
        if (dom_selection && (webkit_dom_dom_selection_get_range_count (dom_selection) > 0)) {
-               WebKitDOMRange *range = NULL;
-               gchar *text = NULL;
-
-               range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-               if (range)
-                       text = webkit_dom_range_to_string (range, NULL);
-               g_clear_object (&range);
+               gchar *text = dom_selection_get_content_text (dom_selection);
                g_clear_object (&dom_selection);
                return text;
        }
@@ -345,6 +355,94 @@ e_dom_utils_get_selection_content_text (WebKitDOMDocument *document)
        return NULL;
 }
 
+static gchar *
+get_frame_selection_content_multipart (WebKitDOMElement *iframe,
+                                       gboolean *is_html)
+{
+       WebKitDOMDocument *content_document;
+       WebKitDOMDOMWindow *dom_window = NULL;
+       WebKitDOMDOMSelection *dom_selection = NULL;
+       WebKitDOMHTMLCollection *frames = NULL;
+       gulong ii, length;
+
+       content_document = webkit_dom_html_iframe_element_get_content_document (
+               WEBKIT_DOM_HTML_IFRAME_ELEMENT (iframe));
+
+       if (!content_document)
+               return NULL;
+
+       dom_window = webkit_dom_document_get_default_view (content_document);
+       dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+       g_clear_object (&dom_window);
+       if (dom_selection && (webkit_dom_dom_selection_get_range_count (dom_selection) > 0)) {
+               gchar *content;
+               gchar *uri = webkit_dom_document_get_document_uri (content_document);
+
+               /* The URI is url encoded.. */
+               if (strstr (uri, "mime_type=text%2Fplain")) {
+                       content = dom_selection_get_content_text (dom_selection);
+                       if (is_html)
+                               *is_html = FALSE;
+               } else {
+                       content = dom_selection_get_content_html (dom_selection, content_document);
+                       if (is_html)
+                               *is_html = TRUE;
+               }
+
+               g_clear_object (&dom_selection);
+               return content;
+       }
+       g_clear_object (&dom_selection);
+
+       frames = webkit_dom_document_get_elements_by_tag_name_as_html_collection (content_document, "iframe");
+       length = webkit_dom_html_collection_get_length (frames);
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *node;
+               gchar *content;
+
+               node = webkit_dom_html_collection_item (frames, ii);
+
+               content = get_frame_selection_content_multipart (WEBKIT_DOM_ELEMENT (node), is_html);
+
+               if (content != NULL) {
+                       g_clear_object (&frames);
+                       return content;
+               }
+       }
+
+       g_clear_object (&frames);
+       return NULL;
+}
+
+gchar *
+e_dom_utils_get_selection_content_multipart (WebKitDOMDocument *document,
+                                             gboolean *is_html)
+{
+       WebKitDOMHTMLCollection *frames = NULL;
+       gulong ii, length;
+
+       frames = webkit_dom_document_get_elements_by_tag_name_as_html_collection (document, "iframe");
+       length = webkit_dom_html_collection_get_length (frames);
+
+       for (ii = 0; ii < length; ii++) {
+               gchar *text;
+               WebKitDOMNode *node;
+
+               node = webkit_dom_html_collection_item (frames, ii);
+
+               text = get_frame_selection_content_multipart (
+                       WEBKIT_DOM_ELEMENT (node), is_html);
+
+               if (text != NULL) {
+                       g_clear_object (&frames);
+                       return text;
+               }
+       }
+
+       g_clear_object (&frames);
+       return NULL;
+}
+
 void
 e_dom_utils_create_and_add_css_style_sheet (WebKitDOMDocument *document,
                                             const gchar *style_sheet_id)
diff --git a/src/web-extensions/e-dom-utils.h b/src/web-extensions/e-dom-utils.h
index 0a7d536..5f0d503 100644
--- a/src/web-extensions/e-dom-utils.h
+++ b/src/web-extensions/e-dom-utils.h
@@ -42,6 +42,9 @@ gchar *               e_dom_utils_get_selection_content_html
                                                (WebKitDOMDocument *document);
 gchar *                e_dom_utils_get_selection_content_text
                                                (WebKitDOMDocument *document);
+gchar *                e_dom_utils_get_selection_content_multipart
+                                               (WebKitDOMDocument *document,
+                                                gboolean *is_html);
 void           e_dom_utils_create_and_add_css_style_sheet
                                                (WebKitDOMDocument *document,
                                                 const gchar *style_sheet_id);
diff --git a/src/web-extensions/e-web-extension.c b/src/web-extensions/e-web-extension.c
index d053d2e..c63ce89 100644
--- a/src/web-extensions/e-web-extension.c
+++ b/src/web-extensions/e-web-extension.c
@@ -105,6 +105,11 @@ static const char introspection_xml[] =
 "      <arg type='t' name='page_id' direction='in'/>"
 "      <arg type='s' name='text_content' direction='out'/>"
 "    </method>"
+"    <method name='GetSelectionContentMultipart'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='content' direction='out'/>"
+"      <arg type='b' name='is_html' direction='out'/>"
+"    </method>"
 "    <method name='CreateAndAddCSSStyleSheet'>"
 "      <arg type='t' name='page_id' direction='in'/>"
 "      <arg type='s' name='style_sheet_id' direction='in'/>"
@@ -538,6 +543,26 @@ handle_method_call (GDBusConnection *connection,
                                "(@s)",
                                g_variant_new_take_string (
                                        html_content ? html_content : g_strdup (""))));
+       } else if (g_strcmp0 (method_name, "GetSelectionContentMultipart") == 0) {
+               gchar *text_content;
+               gboolean is_html = FALSE;
+
+               g_variant_get (parameters, "(t)", &page_id);
+               web_page = get_webkit_web_page_or_return_dbus_error (
+                       invocation, web_extension, page_id);
+               if (!web_page)
+                       return;
+
+               document = webkit_web_page_get_dom_document (web_page);
+               text_content = e_dom_utils_get_selection_content_multipart (document, &is_html);
+
+               g_dbus_method_invocation_return_value (
+                       invocation,
+                       g_variant_new (
+                               "(@sb)",
+                               g_variant_new_take_string (
+                                       text_content ? text_content : g_strdup ("")),
+                               is_html));
        } else if (g_strcmp0 (method_name, "GetSelectionContentText") == 0) {
                gchar *text_content;
 
@@ -551,7 +576,11 @@ handle_method_call (GDBusConnection *connection,
                text_content = e_dom_utils_get_selection_content_text (document);
 
                g_dbus_method_invocation_return_value (
-                       invocation, g_variant_new_take_string (text_content));
+                       invocation,
+                       g_variant_new (
+                               "(@s)",
+                               g_variant_new_take_string (
+                                       text_content ? text_content : g_strdup (""))));
        } else if (g_strcmp0 (method_name, "AddCSSRuleIntoStyleSheet") == 0) {
                const gchar *style_sheet_id, *selector, *style;
 


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