[evolution/wip/webkit2] Bug 743876 - Inline image lost on message send when sending through Outbox
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/wip/webkit2] Bug 743876 - Inline image lost on message send when sending through Outbox
- Date: Wed, 22 Apr 2015 12:53:18 +0000 (UTC)
commit ac277b4c5952d9240173ca7c2a4567edb2519b69
Author: Tomas Popela <tpopela redhat com>
Date: Tue Mar 24 11:19:57 2015 +0100
Bug 743876 - Inline image lost on message send when sending through Outbox
The thing is that when we were sending the message through Outbox
Evolution generates one message that is used for sending and another one
for saving to Outbox. But while creating the first message the images
inside the view are processed to cid images, so for the second message
they were not there. To avoid that we will restore the images in the
view right after we get the HTML version of view's content.
composer/e-msg-composer.c | 3 +-
e-util/e-html-editor-view.c | 238 ++++++++++++---------
e-util/e-html-editor-view.h | 7 +-
e-util/e-html-editor.c | 2 +-
e-util/e-mail-signature-editor.c | 2 +-
e-util/test-html-editor.c | 8 +-
web-extensions/e-html-editor-view-dom-functions.c | 70 ++++++-
web-extensions/e-html-editor-view-dom-functions.h | 3 +-
web-extensions/e-html-editor-web-extension.c | 6 +-
9 files changed, 221 insertions(+), 118 deletions(-)
---
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index 54e7485..26a816a 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -1362,10 +1362,9 @@ composer_build_message (EMsgComposer *composer,
editor = e_msg_composer_get_editor (composer);
view = e_html_editor_get_view (editor);
- inline_images = e_html_editor_view_get_parts_for_inline_images (view, from_domain);
data = g_byte_array_new ();
- text = e_html_editor_view_get_text_html (view);
+ text = e_html_editor_view_get_text_html (view, from_domain, &inline_images);
length = strlen (text);
g_byte_array_append (data, (guint8 *) text, (guint) length);
pre_encode = text_requires_quoted_printable (text, length);
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index 6582119..6ede8ad 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -1762,6 +1762,105 @@ process_document (EHTMLEditorView *view,
return NULL;
}
+static CamelMimePart *
+create_part_for_inline_image_from_element_data (const gchar *element_src,
+ const gchar *name,
+ const gchar *id)
+{
+ CamelStream *stream;
+ CamelDataWrapper *wrapper;
+ CamelMimePart *part = NULL;
+ gsize decoded_size;
+ gssize size;
+ gchar *mime_type = NULL;
+ const gchar *base64_encoded_data;
+ guchar *base64_decoded_data = NULL;
+
+ base64_encoded_data = strstr (element_src, ";base64,");
+ if (!base64_encoded_data)
+ goto out;
+
+ mime_type = g_strndup (
+ element_src + 5,
+ base64_encoded_data - (strstr (element_src, "data:") + 5));
+
+ /* Move to actual data */
+ base64_encoded_data += 8;
+
+ base64_decoded_data = g_base64_decode (base64_encoded_data, &decoded_size);
+
+ stream = camel_stream_mem_new ();
+ size = camel_stream_write (
+ stream, (gchar *) base64_decoded_data, decoded_size, NULL, NULL);
+
+ if (size == -1)
+ goto out;
+
+ wrapper = camel_data_wrapper_new ();
+ camel_data_wrapper_construct_from_stream_sync (
+ wrapper, stream, NULL, NULL);
+ g_object_unref (stream);
+
+ camel_data_wrapper_set_mime_type (wrapper, mime_type);
+
+ part = camel_mime_part_new ();
+ camel_medium_set_content (CAMEL_MEDIUM (part), wrapper);
+ g_object_unref (wrapper);
+
+ camel_mime_part_set_content_id (part, id);
+ camel_mime_part_set_filename (part, name);
+ camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
+out:
+ g_free (mime_type);
+ g_free (base64_decoded_data);
+
+ return part;
+}
+
+static GList *
+html_editor_view_get_parts_for_inline_images (EHTMLEditorView *view,
+ const gchar *uid_domain)
+{
+ GDBusProxy *web_extension;
+ GList *parts = NULL;
+ GVariant *result;
+
+ g_return_val_if_fail (E_IS_HTML_EDITOR_VIEW (view), NULL);
+
+ web_extension = e_html_editor_view_get_web_extension_proxy (view);
+ if (!web_extension)
+ return NULL;
+
+ result = g_dbus_proxy_call_sync (
+ web_extension,
+ "DOMGetInlineImagesData",
+ g_variant_new (
+ "(ts)",
+ webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view)),
+ uid_domain),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL);
+
+ if (result) {
+ const gchar *element_src, *name, *id;
+ GVariantIter *iter;
+
+ g_variant_get (result, "asss", &iter);
+ while (g_variant_iter_loop (iter, "&s&s&s", &element_src, &name, &id)) {
+ CamelMimePart *part;
+
+ part = create_part_for_inline_image_from_element_data (
+ element_src, name, id);
+ parts = g_list_append (parts, part);
+ }
+ g_variant_iter_free (iter);
+ }
+
+ return parts;
+}
+
/**
* e_html_editor_view_get_text_html:
* @view: an #EHTMLEditorView:
@@ -1772,9 +1871,45 @@ process_document (EHTMLEditorView *view,
* Returns: A newly allocated string
*/
gchar *
-e_html_editor_view_get_text_html (EHTMLEditorView *view)
+e_html_editor_view_get_text_html (EHTMLEditorView *view,
+ const gchar *from_domain,
+ GList **inline_images)
{
- return process_document (view, "DOMProcessContentForHTML");
+ GDBusProxy *web_extension;
+ GVariant *result;
+
+ g_return_val_if_fail (E_IS_HTML_EDITOR_VIEW (view), NULL);
+
+ if (inline_images && from_domain)
+ *inline_images = html_editor_view_get_parts_for_inline_images (view, from_domain);
+
+ web_extension = e_html_editor_view_get_web_extension_proxy (view);
+ if (!web_extension)
+ return NULL;
+
+ result = g_dbus_proxy_call_sync (
+ web_extension,
+ "DOMProcessContentForHTML",
+ g_variant_new (
+ "(ts)",
+ webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view)),
+ from_domain),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL);
+
+ if (result) {
+ gchar *value;
+ gsize length = 0;
+
+ value = g_variant_dup_string (result, &length);
+ g_variant_unref (result);
+
+ return value;
+ }
+
+ return NULL;
}
/**
@@ -2489,105 +2624,6 @@ e_html_editor_view_update_fonts (EHTMLEditorView *view)
pango_font_description_free (vw);
}
-static CamelMimePart *
-create_part_for_inline_image_from_element_data (const gchar *element_src,
- const gchar *name,
- const gchar *id)
-{
- CamelStream *stream;
- CamelDataWrapper *wrapper;
- CamelMimePart *part = NULL;
- gsize decoded_size;
- gssize size;
- gchar *mime_type = NULL;
- const gchar *base64_encoded_data;
- guchar *base64_decoded_data = NULL;
-
- base64_encoded_data = strstr (element_src, ";base64,");
- if (!base64_encoded_data)
- goto out;
-
- mime_type = g_strndup (
- element_src + 5,
- base64_encoded_data - (strstr (element_src, "data:") + 5));
-
- /* Move to actual data */
- base64_encoded_data += 8;
-
- base64_decoded_data = g_base64_decode (base64_encoded_data, &decoded_size);
-
- stream = camel_stream_mem_new ();
- size = camel_stream_write (
- stream, (gchar *) base64_decoded_data, decoded_size, NULL, NULL);
-
- if (size == -1)
- goto out;
-
- wrapper = camel_data_wrapper_new ();
- camel_data_wrapper_construct_from_stream_sync (
- wrapper, stream, NULL, NULL);
- g_object_unref (stream);
-
- camel_data_wrapper_set_mime_type (wrapper, mime_type);
-
- part = camel_mime_part_new ();
- camel_medium_set_content (CAMEL_MEDIUM (part), wrapper);
- g_object_unref (wrapper);
-
- camel_mime_part_set_content_id (part, id);
- camel_mime_part_set_filename (part, name);
- camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
-out:
- g_free (mime_type);
- g_free (base64_decoded_data);
-
- return part;
-}
-
-GList *
-e_html_editor_view_get_parts_for_inline_images (EHTMLEditorView *view,
- const gchar *uid_domain)
-{
- GDBusProxy *web_extension;
- GList *parts = NULL;
- GVariant *result;
-
- g_return_val_if_fail (E_IS_HTML_EDITOR_VIEW (view), NULL);
-
- web_extension = e_html_editor_view_get_web_extension_proxy (view);
- if (!web_extension)
- return NULL;
-
- result = g_dbus_proxy_call_sync (
- web_extension,
- "DOMGetInlineImagesData",
- g_variant_new (
- "(ts)",
- webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view)),
- uid_domain),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- NULL);
-
- if (result) {
- const gchar *element_src, *name, *id;
- GVariantIter *iter;
-
- g_variant_get (result, "asss", &iter);
- while (g_variant_iter_loop (iter, "&s&s&s", &element_src, &name, &id)) {
- CamelMimePart *part;
-
- part = create_part_for_inline_image_from_element_data (
- element_src, name, id);
- parts = g_list_append (parts, part);
- }
- g_variant_iter_free (iter);
- }
-
- return parts;
-}
-
/**
* e_html_editor_view_add_inline_image_from_mime_part:
* @composer: a composer object
diff --git a/e-util/e-html-editor-view.h b/e-util/e-html-editor-view.h
index f59df15..bb12c83 100644
--- a/e-util/e-html-editor-view.h
+++ b/e-util/e-html-editor-view.h
@@ -136,7 +136,9 @@ void e_html_editor_view_set_magic_smileys
ESpellChecker * e_html_editor_view_get_spell_checker
(EHTMLEditorView *view);
gchar * e_html_editor_view_get_text_html
- (EHTMLEditorView *view);
+ (EHTMLEditorView *view,
+ const gchar *from_domain,
+ GList **inline_images);
gchar * e_html_editor_view_get_text_html_for_drafts
(EHTMLEditorView *view);
gchar * e_html_editor_view_get_text_plain
@@ -170,9 +172,6 @@ void e_html_editor_view_dequote_plain_text
void e_html_editor_view_add_inline_image_from_mime_part
(EHTMLEditorView *view,
CamelMimePart *part);
-GList * e_html_editor_view_get_parts_for_inline_images
- (EHTMLEditorView *view,
- const gchar *uid_domain);
gboolean e_html_editor_view_is_message_from_draft
(EHTMLEditorView *view);
void e_html_editor_view_set_is_message_from_draft
diff --git a/e-util/e-html-editor.c b/e-util/e-html-editor.c
index 8fe1c16..8e74309 100644
--- a/e-util/e-html-editor.c
+++ b/e-util/e-html-editor.c
@@ -1151,7 +1151,7 @@ e_html_editor_save (EHTMLEditor *editor,
if (as_html)
content = e_html_editor_view_get_text_html (
- E_HTML_EDITOR_VIEW (editor));
+ E_HTML_EDITOR_VIEW (editor), NULL, NULL);
else
content = e_html_editor_view_get_text_plain (
E_HTML_EDITOR_VIEW (editor));
diff --git a/e-util/e-mail-signature-editor.c b/e-util/e-mail-signature-editor.c
index 1b5173d..9b0f29e 100644
--- a/e-util/e-mail-signature-editor.c
+++ b/e-util/e-mail-signature-editor.c
@@ -855,7 +855,7 @@ e_mail_signature_editor_commit (EMailSignatureEditor *window,
if (e_html_editor_view_get_html_mode (view)) {
mime_type = "text/html";
- contents = e_html_editor_view_get_text_html (view);
+ contents = e_html_editor_view_get_text_html (view, NULL, NULL);
} else {
mime_type = "text/plain";
contents = e_html_editor_view_get_text_plain (view);
diff --git a/e-util/test-html-editor.c b/e-util/test-html-editor.c
index 9bb8a3b..e393f87 100644
--- a/e-util/test-html-editor.c
+++ b/e-util/test-html-editor.c
@@ -166,10 +166,14 @@ view_source_dialog (EHTMLEditor *editor,
if (plain_text) {
html = e_html_editor_view_get_text_plain (
- e_html_editor_get_view (editor));
+ e_html_editor_get_view (editor));
} else {
+ GList *inline_images;
+
html = e_html_editor_view_get_text_html (
- e_html_editor_get_view (editor));
+ e_html_editor_get_view (editor), "test-domain", &inline_images);
+
+ g_list_free_full (inline_images, g_object_unref);
}
if (show_source || plain_text) {
diff --git a/web-extensions/e-html-editor-view-dom-functions.c
b/web-extensions/e-html-editor-view-dom-functions.c
index b717c73..2fc9f4b 100644
--- a/web-extensions/e-html-editor-view-dom-functions.c
+++ b/web-extensions/e-html-editor-view-dom-functions.c
@@ -5679,14 +5679,65 @@ dom_process_content_for_plain_text (WebKitDOMDocument *document,
return g_string_free (plain_text, FALSE);
}
+static void
+restore_image (WebKitDOMDocument *document,
+ const gchar *id,
+ const gchar *element_src)
+{
+ gchar *selector;
+ gint length, ii;
+ WebKitDOMNodeList *list;
+
+ selector = g_strconcat ("[data-inline][background=\"cid:", id, "\"]", NULL);
+ list = webkit_dom_document_query_selector_all (document, selector, NULL);
+ length = webkit_dom_node_list_get_length (list);
+ for (ii = 0; ii < length; ii++) {
+ WebKitDOMElement *element = WEBKIT_DOM_ELEMENT (
+ webkit_dom_node_list_item (list, ii));
+
+ webkit_dom_element_set_attribute (element, "background", element_src, NULL);
+ }
+ g_free (selector);
+ g_object_unref (list);
+
+ selector = g_strconcat ("[data-inline][src=\"cid:", id, "\"]", NULL);
+ list = webkit_dom_document_query_selector_all (document, selector, NULL);
+ length = webkit_dom_node_list_get_length (list);
+ for (ii = 0; ii < length; ii++) {
+ WebKitDOMElement *element = WEBKIT_DOM_ELEMENT (
+ webkit_dom_node_list_item (list, ii));
+
+ webkit_dom_element_set_attribute (element, "src", element_src, NULL);
+ }
+ g_free (selector);
+ g_object_unref (list);
+}
+
+static void
+dom_restore_images (WebKitDOMDocument *document,
+ GVariant *inline_images_to_restore)
+{
+ const gchar *element_src, *name, *id;
+ GVariantIter *iter;
+
+ g_variant_get (inline_images_to_restore, "asss", &iter);
+ while (g_variant_iter_loop (iter, "&s&s&s", &element_src, &name, &id))
+ restore_image (document, id, element_src);
+}
+
gchar *
dom_process_content_for_html (WebKitDOMDocument *document,
- EHTMLEditorWebExtension *extension)
+ EHTMLEditorWebExtension *extension,
+ const gchar *from_domain)
{
+ GVariant *inline_images_to_restore = NULL;
gchar *html_content;
WebKitDOMElement *marker;
WebKitDOMNode *node, *document_clone;
+ if (from_domain != NULL)
+ inline_images_to_restore = dom_get_inline_images_data (document, extension, from_domain);
+
document_clone = webkit_dom_node_clone_node (
WEBKIT_DOM_NODE (webkit_dom_document_get_document_element (document)), TRUE);
node = WEBKIT_DOM_NODE (webkit_dom_element_query_selector (
@@ -5716,6 +5767,11 @@ dom_process_content_for_html (WebKitDOMDocument *document,
g_object_unref (document_clone);
+ if (from_domain && inline_images_to_restore) {
+ dom_restore_images (document, inline_images_to_restore);
+ g_object_unref (inline_images_to_restore);
+ }
+
return html_content;
}
@@ -5935,7 +5991,7 @@ dom_get_inline_images_data (WebKitDOMDocument *document,
const gchar *uid_domain)
{
GVariant *result;
- GVariantBuilder *builder;
+ GVariantBuilder *builder = NULL;
GHashTable *added;
gint length, ii;
WebKitDOMNodeList *list;
@@ -5944,7 +6000,7 @@ dom_get_inline_images_data (WebKitDOMDocument *document,
length = webkit_dom_node_list_get_length (list);
if (length == 0)
- return NULL;
+ goto background;
builder = g_variant_builder_new (G_VARIANT_TYPE ("asss"));
@@ -5978,9 +6034,15 @@ dom_get_inline_images_data (WebKitDOMDocument *document,
}
g_object_unref (list);
+ background:
list = webkit_dom_document_query_selector_all (
document, "[data-inline][background]", NULL);
length = webkit_dom_node_list_get_length (list);
+ if (length == 0)
+ goto out;
+ if (!builder)
+ builder = g_variant_builder_new (G_VARIANT_TYPE ("asss"));
+
for (ii = 0; ii < length; ii++) {
const gchar *id;
gchar *cid = NULL;
@@ -6011,7 +6073,7 @@ dom_get_inline_images_data (WebKitDOMDocument *document,
}
g_free (cid);
}
-
+ out:
g_object_unref (list);
g_hash_table_destroy (added);
diff --git a/web-extensions/e-html-editor-view-dom-functions.h
b/web-extensions/e-html-editor-view-dom-functions.h
index d743df0..90ab560 100644
--- a/web-extensions/e-html-editor-view-dom-functions.h
+++ b/web-extensions/e-html-editor-view-dom-functions.h
@@ -94,7 +94,8 @@ gchar * dom_process_content_for_plain_text
EHTMLEditorWebExtension *extension);
gchar * dom_process_content_for_html (WebKitDOMDocument *document,
- EHTMLEditorWebExtension *extension);
+ EHTMLEditorWebExtension *extension,
+ const gchar *from_domain);
gboolean dom_check_if_conversion_needed (WebKitDOMDocument *document);
diff --git a/web-extensions/e-html-editor-web-extension.c b/web-extensions/e-html-editor-web-extension.c
index 44a6d52..cce8949 100644
--- a/web-extensions/e-html-editor-web-extension.c
+++ b/web-extensions/e-html-editor-web-extension.c
@@ -422,6 +422,7 @@ static const char introspection_xml[] =
" </method>"
" <method name='DOMProcessContentForHTML'>"
" <arg type='t' name='page_id' direction='in'/>"
+" <arg type='s' name='from_domain' direction='in'/>"
" <arg type='s' name='content' direction='out'/>"
" </method>"
" <method name='DOMProcessContentForDraft'>"
@@ -1478,9 +1479,10 @@ handle_method_call (GDBusConnection *connection,
invocation,
value ? g_variant_new_take_string (value) : NULL);
} else if (g_strcmp0 (method_name, "DOMProcessContentForHTML") == 0) {
+ const gchar *from_domain;
gchar *value = NULL;
- g_variant_get (parameters, "(t)", &page_id);
+ g_variant_get (parameters, "(t&s)", &page_id, &from_domain);
web_page = get_webkit_web_page_or_return_dbus_error (
invocation, web_extension, page_id);
@@ -1488,7 +1490,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- value = dom_process_content_for_html (document, extension);
+ value = dom_process_content_for_html (document, extension, from_domain);
g_dbus_method_invocation_return_value (
invocation,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]