4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21 #include "evolution-config.h"
23 #include <glib/gi18n.h>
24 #include <glib/gstdio.h>
27 #include <camel/camel.h>
29 #include <em-format/e-mail-extension-registry.h>
30 #include <em-format/e-mail-formatter-enumtypes.h>
31 #include <em-format/e-mail-formatter-extension.h>
32 #include <em-format/e-mail-formatter-print.h>
33 #include <em-format/e-mail-part-attachment.h>
34 #include <em-format/e-mail-part-utils.h>
36 #include "shell/e-shell-utils.h"
38 #include "e-cid-request.h"
39 #include "e-http-request.h"
40 #include "e-mail-display-popup-extension.h"
41 #include "e-mail-notes.h"
42 #include "e-mail-request.h"
43 #include "e-mail-ui-session.h"
44 #include "em-composer-utils.h"
47 #include "web-extensions/e-web-extension-names.h"
49 #include "e-mail-display.h"
53 #define E_MAIL_DISPLAY_GET_PRIVATE(obj) \
54 (G_TYPE_INSTANCE_GET_PRIVATE \
55 ((obj), E_TYPE_MAIL_DISPLAY, EMailDisplayPrivate))
58 E_ATTACHMENT_FLAG_VISIBLE
= (1 << 0),
59 E_ATTACHMENT_FLAG_ZOOMED_TO_100
= (1 << 1)
62 struct _EMailDisplayPrivate
{
63 EAttachmentStore
*attachment_store
;
64 EAttachmentView
*attachment_view
;
65 GHashTable
*attachment_flags
; /* EAttachment * ~> guint bit-or of EAttachmentFlags */
66 guint attachment_inline_ui_id
;
68 GtkActionGroup
*attachment_inline_group
;
70 EMailPartList
*part_list
;
71 EMailFormatterMode mode
;
72 EMailFormatter
*formatter
;
74 gboolean headers_collapsable
;
75 gboolean headers_collapsed
;
76 gboolean force_image_load
;
80 guint scheduled_reload
;
82 GHashTable
*old_settings
;
84 GMutex remote_content_lock
;
85 EMailRemoteContent
*remote_content
;
86 GHashTable
*skipped_remote_content_sites
;
88 guint web_extension_headers_collapsed_signal_id
;
89 guint web_extension_mail_part_appeared_signal_id
;
94 PROP_ATTACHMENT_STORE
,
97 PROP_HEADERS_COLLAPSABLE
,
98 PROP_HEADERS_COLLAPSED
,
104 static CamelDataCache
*emd_global_http_cache
= NULL
;
106 static const gchar
*ui
=
108 " <popup name='context'>"
109 " <placeholder name='custom-actions-1'>"
110 " <menuitem action='add-to-address-book'/>"
111 " <menuitem action='send-reply'/>"
113 " <placeholder name='custom-actions-3'>"
114 " <menu action='search-folder-menu'>"
115 " <menuitem action='search-folder-recipient'/>"
116 " <menuitem action='search-folder-sender'/>"
122 static GtkActionEntry mailto_entries
[] = {
124 { "add-to-address-book",
126 N_("_Add to Address Book..."),
128 NULL
, /* XXX Add a tooltip! */
129 NULL
/* Handled by EMailReader */ },
131 { "search-folder-recipient",
133 N_("_To This Address"),
135 NULL
, /* XXX Add a tooltip! */
136 NULL
/* Handled by EMailReader */ },
138 { "search-folder-sender",
140 N_("_From This Address"),
142 NULL
, /* XXX Add a tooltip! */
143 NULL
/* Handled by EMailReader */ },
147 N_("Send _Reply To..."),
149 N_("Send a reply message to this address"),
150 NULL
/* Handled by EMailReader */ },
154 { "search-folder-menu",
155 "folder-saved-search",
156 N_("Create Search _Folder"),
167 static const gchar
*attachment_popup_ui
=
169 " <popup name='context'>"
170 " <placeholder name='inline-actions'>"
171 " <menuitem action='zoom-to-100'/>"
172 " <menuitem action='zoom-to-window'/>"
173 " <menuitem action='show'/>"
174 " <menuitem action='show-all'/>"
176 " <menuitem action='hide'/>"
177 " <menuitem action='hide-all'/>"
183 e_mail_display_claim_skipped_uri (EMailDisplay
*mail_display
,
189 g_return_if_fail (E_IS_MAIL_DISPLAY (mail_display
));
190 g_return_if_fail (uri
!= NULL
);
192 /* Do not store anything if the user doesn't want to see the notification */
193 if (!g_settings_get_boolean (mail_display
->priv
->settings
, "notify-remote-content"))
196 soup_uri
= soup_uri_new (uri
);
200 site
= soup_uri_get_host (soup_uri
);
202 g_mutex_lock (&mail_display
->priv
->remote_content_lock
);
204 if (!g_hash_table_contains (mail_display
->priv
->skipped_remote_content_sites
, site
)) {
205 g_hash_table_insert (mail_display
->priv
->skipped_remote_content_sites
, g_strdup (site
), NULL
);
208 g_mutex_unlock (&mail_display
->priv
->remote_content_lock
);
211 soup_uri_free (soup_uri
);
215 e_mail_display_cleanup_skipped_uris (EMailDisplay
*mail_display
)
217 g_return_if_fail (E_IS_MAIL_DISPLAY (mail_display
));
219 g_mutex_lock (&mail_display
->priv
->remote_content_lock
);
220 g_hash_table_remove_all (mail_display
->priv
->skipped_remote_content_sites
);
221 g_mutex_unlock (&mail_display
->priv
->remote_content_lock
);
225 e_mail_display_can_download_uri (EMailDisplay
*mail_display
,
230 gboolean can_download
= FALSE
;
231 EMailRemoteContent
*remote_content
;
233 g_return_val_if_fail (E_IS_MAIL_DISPLAY (mail_display
), FALSE
);
234 g_return_val_if_fail (uri
!= NULL
, FALSE
);
236 remote_content
= e_mail_display_ref_remote_content (mail_display
);
240 soup_uri
= soup_uri_new (uri
);
242 g_object_unref (remote_content
);
246 site
= soup_uri_get_host (soup_uri
);
248 can_download
= e_mail_remote_content_has_site (remote_content
, site
);
250 soup_uri_free (soup_uri
);
252 if (!can_download
&& mail_display
->priv
->part_list
) {
253 CamelMimeMessage
*message
;
255 message
= e_mail_part_list_get_message (mail_display
->priv
->part_list
);
257 CamelInternetAddress
*from
;
259 from
= camel_mime_message_get_from (message
);
263 len
= camel_address_length (CAMEL_ADDRESS (from
));
264 for (ii
= 0; ii
< len
&& !can_download
; ii
++) {
265 const gchar
*mail
= NULL
;
267 if (!camel_internet_address_get (from
, ii
, NULL
, &mail
))
271 can_download
= e_mail_remote_content_has_mail (remote_content
, mail
);
277 g_object_unref (remote_content
);
283 formatter_image_loading_policy_changed_cb (GObject
*object
,
287 EMailDisplay
*display
= user_data
;
288 EMailFormatter
*formatter
= E_MAIL_FORMATTER (object
);
289 EImageLoadingPolicy policy
;
291 policy
= e_mail_formatter_get_image_loading_policy (formatter
);
293 if (policy
== E_IMAGE_LOADING_POLICY_ALWAYS
)
294 e_mail_display_load_images (display
);
296 e_mail_display_reload (display
);
300 mail_display_update_formatter_colors (EMailDisplay
*display
)
302 EMailFormatter
*formatter
;
303 GtkStateFlags state_flags
;
305 formatter
= display
->priv
->formatter
;
306 state_flags
= gtk_widget_get_state_flags (GTK_WIDGET (display
));
308 if (formatter
!= NULL
)
309 e_mail_formatter_update_style (formatter
, state_flags
);
313 mail_display_process_mailto (EWebView
*web_view
,
314 const gchar
*mailto_uri
,
317 gboolean handled
= FALSE
;
319 g_return_val_if_fail (E_IS_WEB_VIEW (web_view
), FALSE
);
320 g_return_val_if_fail (mailto_uri
!= NULL
, FALSE
);
322 if (g_ascii_strncasecmp (mailto_uri
, "mailto:", 7) == 0) {
324 EMailPartList
*part_list
;
326 part_list
= E_MAIL_DISPLAY (web_view
)->priv
->part_list
;
328 shell
= e_shell_get_default ();
329 em_utils_compose_new_message_with_mailto_and_selection (shell
, mailto_uri
,
330 e_mail_part_list_get_folder (part_list
),
331 e_mail_part_list_get_message_uid (part_list
));
340 decide_policy_cb (WebKitWebView
*web_view
,
341 WebKitPolicyDecision
*decision
,
342 WebKitPolicyDecisionType type
)
344 WebKitNavigationPolicyDecision
*navigation_decision
;
345 WebKitNavigationAction
*navigation_action
;
346 WebKitURIRequest
*request
;
349 if (type
!= WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION
)
352 navigation_decision
= WEBKIT_NAVIGATION_POLICY_DECISION (decision
);
353 navigation_action
= webkit_navigation_policy_decision_get_navigation_action (navigation_decision
);
354 request
= webkit_navigation_action_get_request (navigation_action
);
356 uri
= webkit_uri_request_get_uri (request
);
359 webkit_policy_decision_ignore (decision
);
363 if (g_str_has_prefix (uri
, "file://")) {
366 filename
= g_filename_from_uri (uri
, NULL
, NULL
);
368 if (g_file_test (filename
, G_FILE_TEST_IS_DIR
)) {
369 webkit_policy_decision_ignore (decision
);
370 /* FIXME WK2 Not sure if the request will be changed there */
371 webkit_uri_request_set_uri (request
, "about:blank");
379 if (mail_display_process_mailto (E_WEB_VIEW (web_view
), uri
, NULL
)) {
380 /* do nothing, function handled the "mailto:" uri already */
381 webkit_policy_decision_ignore (decision
);
384 } else if (g_ascii_strncasecmp (uri
, "thismessage:", 12) == 0) {
386 webkit_policy_decision_ignore (decision
);
389 } else if (g_ascii_strncasecmp (uri
, "cid:", 4) == 0) {
391 webkit_policy_decision_ignore (decision
);
396 /* Let WebKit handle it. */
401 add_color_css_rule_for_web_view (EWebView
*view
,
402 const gchar
*color_name
,
403 const gchar
*color_value
)
408 selector
= g_strconcat (".-e-mail-formatter-", color_name
, NULL
);
410 if (g_strstr_len (color_name
, -1, "header")) {
411 style
= g_strconcat (
412 "color: ", color_value
, " !important;", NULL
);
413 } else if (g_strstr_len (color_name
, -1, "frame")) {
414 style
= g_strconcat (
415 "border-color: ", color_value
, NULL
);
417 style
= g_strconcat (
418 "background-color: ", color_value
, " !important;", NULL
);
421 e_web_view_add_css_rule_into_style_sheet (
423 "-e-mail-formatter-style-sheet",
432 initialize_web_view_colors (EMailDisplay
*display
)
434 EMailFormatter
*formatter
;
435 GtkTextDirection direction
;
439 const gchar
*color_names
[] = {
447 formatter
= e_mail_display_get_formatter (display
);
449 for (ii
= 0; color_names
[ii
]; ii
++) {
450 GdkRGBA
*color
= NULL
;
453 g_object_get (formatter
, color_names
[ii
], &color
, NULL
);
454 color_value
= g_strdup_printf ("#%06x", e_rgba_to_value (color
));
456 add_color_css_rule_for_web_view (
457 E_WEB_VIEW (display
),
461 gdk_rgba_free (color
);
462 g_free (color_value
);
465 e_web_view_add_css_rule_into_style_sheet (
466 E_WEB_VIEW (display
),
467 "-e-mail-formatter-style-sheet",
468 ".-e-mail-formatter-frame-security-none",
469 "border-width: 1px; border-style: solid");
471 /* the rgba values below were copied from e-formatter-secure-button */
472 direction
= gtk_widget_get_default_direction ();
474 if (direction
== GTK_TEXT_DIR_RTL
)
475 style
= "border-width: 1px 1px 1px 4px; border-style: solid; border-color: rgba(53%, 73%, 53%, 1.0)";
477 style
= "border-width: 1px 4px 1px 1px; border-style: solid; border-color: rgba(53%, 73%, 53%, 1.0)";
478 e_web_view_add_css_rule_into_style_sheet (
479 E_WEB_VIEW (display
),
480 "-e-mail-formatter-style-sheet",
481 ".-e-mail-formatter-frame-security-good",
484 if (direction
== GTK_TEXT_DIR_RTL
)
485 style
= "border-width: 1px 1px 1px 4px; border-style: solid; border-color: rgba(73%, 53%, 53%, 1.0)";
487 style
= "border-width: 1px 4px 1px 1px; border-style: solid; border-color: rgba(73%, 53%, 53%, 1.0)";
488 e_web_view_add_css_rule_into_style_sheet (
489 E_WEB_VIEW (display
),
490 "-e-mail-formatter-style-sheet",
491 ".-e-mail-formatter-frame-security-bad",
494 if (direction
== GTK_TEXT_DIR_RTL
)
495 style
= "border-width: 1px 1px 1px 4px; border-style: solid; border-color: rgba(91%, 82%, 13%, 1.0)";
497 style
= "border-width: 1px 4px 1px 1px; border-style: solid; border-color: rgba(91%, 82%, 13%, 1.0)";
498 e_web_view_add_css_rule_into_style_sheet (
499 E_WEB_VIEW (display
),
500 "-e-mail-formatter-style-sheet",
501 ".-e-mail-formatter-frame-security-unknown",
504 if (direction
== GTK_TEXT_DIR_RTL
)
505 style
= "border-width: 1px 1px 1px 4px; border-style: solid; border-color: rgba(91%, 82%, 13%, 1.0)";
507 style
= "border-width: 1px 4px 1px 1px; border-style: solid; border-color: rgba(91%, 82%, 13%, 1.0)";
508 e_web_view_add_css_rule_into_style_sheet (
509 E_WEB_VIEW (display
),
510 "-e-mail-formatter-style-sheet",
511 ".-e-mail-formatter-frame-security-need-key",
516 headers_collapsed_signal_cb (GDBusConnection
*connection
,
517 const gchar
*sender_name
,
518 const gchar
*object_path
,
519 const gchar
*interface_name
,
520 const gchar
*signal_name
,
521 GVariant
*parameters
,
522 EMailDisplay
*display
)
524 gboolean collapsed
= FALSE
;
526 if (g_strcmp0 (signal_name
, "HeadersCollapsed") != 0)
530 g_variant_get (parameters
, "(b)", &collapsed
);
532 e_mail_display_set_headers_collapsed (display
, collapsed
);
536 mail_display_mail_part_appeared_signal_cb (GDBusConnection
*connection
,
537 const gchar
*sender_name
,
538 const gchar
*object_path
,
539 const gchar
*interface_name
,
540 const gchar
*signal_name
,
541 GVariant
*parameters
,
544 EMailDisplay
*display
= user_data
;
545 const gchar
*part_id
= NULL
;
549 if (g_strcmp0 (signal_name
, "MailPartAppeared") != 0)
552 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
554 if (!parameters
|| !display
->priv
->part_list
)
557 g_variant_get (parameters
, "(t&s)", &page_id
, &part_id
);
559 if (!part_id
|| !*part_id
|| page_id
!= webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (display
)))
562 part
= e_mail_part_list_ref_part (display
->priv
->part_list
, part_id
);
563 if (part
&& g_strcmp0 (e_mail_part_get_id (part
), part_id
) == 0) {
564 e_mail_part_bind_dom_element (part
, E_WEB_VIEW (display
), page_id
, part_id
);
567 g_clear_object (&part
);
571 setup_dom_bindings (EMailDisplay
*display
)
573 GDBusProxy
*web_extension
;
575 web_extension
= e_web_view_get_web_extension_proxy (E_WEB_VIEW (display
));
578 if (display
->priv
->web_extension_headers_collapsed_signal_id
== 0) {
579 display
->priv
->web_extension_headers_collapsed_signal_id
=
580 g_dbus_connection_signal_subscribe (
581 g_dbus_proxy_get_connection (web_extension
),
582 g_dbus_proxy_get_name (web_extension
),
583 E_WEB_EXTENSION_INTERFACE
,
585 E_WEB_EXTENSION_OBJECT_PATH
,
587 G_DBUS_SIGNAL_FLAGS_NONE
,
588 (GDBusSignalCallback
) headers_collapsed_signal_cb
,
593 if (display
->priv
->web_extension_mail_part_appeared_signal_id
== 0) {
594 display
->priv
->web_extension_mail_part_appeared_signal_id
=
595 g_dbus_connection_signal_subscribe (
596 g_dbus_proxy_get_connection (web_extension
),
597 g_dbus_proxy_get_name (web_extension
),
598 E_WEB_EXTENSION_INTERFACE
,
600 E_WEB_EXTENSION_OBJECT_PATH
,
602 G_DBUS_SIGNAL_FLAGS_NONE
,
603 mail_display_mail_part_appeared_signal_cb
,
608 e_util_invoke_g_dbus_proxy_call_with_error_check (
610 "EMailDisplayBindDOM",
613 webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (display
))),
619 mail_display_change_one_attachment_visibility (EMailDisplay
*display
,
620 EAttachment
*attachment
,
628 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
629 g_return_if_fail (E_IS_ATTACHMENT (attachment
));
630 g_return_if_fail (g_hash_table_contains (display
->priv
->attachment_flags
, attachment
));
632 flags
= GPOINTER_TO_UINT (g_hash_table_lookup (display
->priv
->attachment_flags
, attachment
));
634 show
= !(flags
& E_ATTACHMENT_FLAG_VISIBLE
);
636 if ((((flags
& E_ATTACHMENT_FLAG_VISIBLE
) != 0) ? 1 : 0) == (show
? 1 : 0))
640 flags
= flags
| E_ATTACHMENT_FLAG_VISIBLE
;
642 flags
= flags
& (~E_ATTACHMENT_FLAG_VISIBLE
);
643 g_hash_table_insert (display
->priv
->attachment_flags
, attachment
, GUINT_TO_POINTER (flags
));
645 element_id
= g_strdup_printf ("attachment-wrapper-%p", attachment
);
646 e_web_view_set_element_hidden (E_WEB_VIEW (display
), element_id
, !show
);
649 element_id
= g_strdup_printf ("attachment-expander-img-%p", attachment
);
650 uri
= g_strdup_printf ("gtk-stock://%s?size=%d", show
? "go-down" : "go-next", GTK_ICON_SIZE_BUTTON
);
652 e_web_view_set_element_attribute (E_WEB_VIEW (display
), element_id
, NULL
, "src", uri
);
659 mail_display_change_attachment_visibility (EMailDisplay
*display
,
663 EAttachmentView
*view
;
664 GList
*attachments
, *link
;
666 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
668 view
= e_mail_display_get_attachment_view (display
);
669 g_return_if_fail (view
!= NULL
);
672 attachments
= e_attachment_store_get_attachments (display
->priv
->attachment_store
);
674 attachments
= view
? e_attachment_view_get_selected_attachments (view
) : NULL
;
676 for (link
= attachments
; link
; link
= g_list_next (link
)) {
677 EAttachment
*attachment
= link
->data
;
679 if (e_attachment_get_can_show (attachment
))
680 mail_display_change_one_attachment_visibility (display
, attachment
, show
, FALSE
);
683 g_list_free_full (attachments
, g_object_unref
);
687 mail_attachment_change_zoom (EMailDisplay
*display
,
688 gboolean to_100_percent
)
690 EAttachmentView
*view
;
691 GList
*attachments
, *link
;
693 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
695 view
= e_mail_display_get_attachment_view (display
);
696 g_return_if_fail (view
!= NULL
);
698 attachments
= view
? e_attachment_view_get_selected_attachments (view
) : NULL
;
700 for (link
= attachments
; link
; link
= g_list_next (link
)) {
701 EAttachment
*attachment
= link
->data
;
703 const gchar
*max_width
;
706 if (!E_IS_ATTACHMENT (attachment
) ||
707 !g_hash_table_contains (display
->priv
->attachment_flags
, attachment
))
710 flags
= GPOINTER_TO_UINT (g_hash_table_lookup (display
->priv
->attachment_flags
, attachment
));
711 if ((((flags
& E_ATTACHMENT_FLAG_ZOOMED_TO_100
) != 0) ? 1 : 0) == (to_100_percent
? 1 : 0))
715 flags
= flags
| E_ATTACHMENT_FLAG_ZOOMED_TO_100
;
717 flags
= flags
& (~E_ATTACHMENT_FLAG_ZOOMED_TO_100
);
718 g_hash_table_insert (display
->priv
->attachment_flags
, attachment
, GUINT_TO_POINTER (flags
));
725 element_id
= g_strdup_printf ("attachment-wrapper-%p::child", attachment
);
727 e_web_view_set_element_style_property (E_WEB_VIEW (display
), element_id
, "max-width", max_width
, "");
732 g_list_free_full (attachments
, g_object_unref
);
736 action_attachment_show_cb (GtkAction
*action
,
737 EMailDisplay
*display
)
739 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
741 mail_display_change_attachment_visibility (display
, FALSE
, TRUE
);
745 action_attachment_show_all_cb (GtkAction
*action
,
746 EMailDisplay
*display
)
748 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
750 mail_display_change_attachment_visibility (display
, TRUE
, TRUE
);
754 action_attachment_hide_cb (GtkAction
*action
,
755 EMailDisplay
*display
)
757 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
759 mail_display_change_attachment_visibility (display
, FALSE
, FALSE
);
763 action_attachment_hide_all_cb (GtkAction
*action
,
764 EMailDisplay
*display
)
766 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
768 mail_display_change_attachment_visibility (display
, TRUE
, FALSE
);
772 action_attachment_zoom_to_100_cb (GtkAction
*action
,
773 EMailDisplay
*display
)
775 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
777 mail_attachment_change_zoom (display
, TRUE
);
781 action_attachment_zoom_to_window_cb (GtkAction
*action
,
782 EMailDisplay
*display
)
784 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
786 mail_attachment_change_zoom (display
, FALSE
);
789 static GtkActionEntry attachment_inline_entries
[] = {
795 NULL
, /* XXX Add a tooltip! */
796 G_CALLBACK (action_attachment_hide_cb
) },
802 NULL
, /* XXX Add a tooltip! */
803 G_CALLBACK (action_attachment_hide_all_cb
) },
809 NULL
, /* XXX Add a tooltip! */
810 G_CALLBACK (action_attachment_show_cb
) },
814 N_("Vie_w All Inline"),
816 NULL
, /* XXX Add a tooltip! */
817 G_CALLBACK (action_attachment_show_all_cb
) },
823 N_("Zoom the image to its natural size"),
824 G_CALLBACK (action_attachment_zoom_to_100_cb
) },
828 N_("_Zoom to window"),
830 N_("Zoom large images to not be wider than the window width"),
831 G_CALLBACK (action_attachment_zoom_to_window_cb
) }
835 mail_display_ref_attachment_from_element (EMailDisplay
*display
,
836 const gchar
*element_value
)
838 EAttachment
*attachment
= NULL
;
839 GQueue queue
= G_QUEUE_INIT
;
842 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), NULL
);
843 g_return_val_if_fail (element_value
!= NULL
, NULL
);
845 e_mail_part_list_queue_parts (display
->priv
->part_list
, NULL
, &queue
);
846 head
= g_queue_peek_head_link (&queue
);
848 for (link
= head
; link
!= NULL
; link
= g_list_next (link
)) {
849 EMailPart
*part
= E_MAIL_PART (link
->data
);
851 if (E_IS_MAIL_PART_ATTACHMENT (part
)) {
856 adept
= e_mail_part_attachment_ref_attachment (E_MAIL_PART_ATTACHMENT (part
));
858 tmp
= g_strdup_printf ("%p", adept
);
859 can_use
= g_strcmp0 (tmp
, element_value
) == 0;
867 g_clear_object (&adept
);
871 while (!g_queue_is_empty (&queue
))
872 g_object_unref (g_queue_pop_head (&queue
));
878 call_attachment_save_handle_error (GObject
*source_object
,
879 GAsyncResult
*result
,
882 GtkWindow
*window
= user_data
;
884 g_return_if_fail (E_IS_ATTACHMENT (source_object
));
885 g_return_if_fail (!window
|| GTK_IS_WINDOW (window
));
887 e_attachment_save_handle_error (E_ATTACHMENT (source_object
), result
, window
);
889 g_clear_object (&window
);
893 mail_display_attachment_expander_clicked_cb (EWebView
*web_view
,
894 const gchar
*element_class
,
895 const gchar
*element_value
,
896 const GtkAllocation
*element_position
,
899 EMailDisplay
*display
;
900 EAttachment
*attachment
;
902 g_return_if_fail (E_IS_MAIL_DISPLAY (web_view
));
903 g_return_if_fail (element_class
!= NULL
);
904 g_return_if_fail (element_value
!= NULL
);
905 g_return_if_fail (element_position
!= NULL
);
907 display
= E_MAIL_DISPLAY (web_view
);
908 attachment
= mail_display_ref_attachment_from_element (display
, element_value
);
911 if (e_attachment_get_can_show (attachment
)) {
912 /* Flip the current 'visible' state */
913 mail_display_change_one_attachment_visibility (display
, attachment
, FALSE
, TRUE
);
915 GAppInfo
*default_app
;
918 parent
= gtk_widget_get_toplevel (GTK_WIDGET (web_view
));
919 parent
= gtk_widget_is_toplevel (parent
) ? parent
: NULL
;
921 /* Either open in the default application... */
922 default_app
= e_attachment_ref_default_app (attachment
);
924 e_attachment_open_async (
925 attachment
, default_app
, (GAsyncReadyCallback
)
926 e_attachment_open_handle_error
, parent
);
928 g_object_unref (default_app
);
932 EAttachmentStore
*store
;
935 store
= e_mail_display_get_attachment_store (display
);
936 attachments
= g_list_prepend (NULL
, attachment
);
938 destination
= e_attachment_store_run_save_dialog (store
, attachments
, parent
);
940 e_attachment_save_async (
941 attachment
, destination
, (GAsyncReadyCallback
)
942 call_attachment_save_handle_error
, parent
? g_object_ref (parent
) : NULL
);
944 g_object_unref (destination
);
947 g_list_free (attachments
);
952 g_clear_object (&attachment
);
956 mail_display_attachment_inline_update_actions (EMailDisplay
*display
)
958 GtkActionGroup
*action_group
;
960 GList
*attachments
, *link
;
961 EAttachmentView
*view
;
964 guint n_selected
= 0;
965 gboolean can_show
= FALSE
;
966 gboolean shown
= FALSE
;
967 gboolean is_image
= FALSE
;
968 gboolean zoomed_to_100
= FALSE
;
971 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
973 action_group
= display
->priv
->attachment_inline_group
;
974 g_return_if_fail (action_group
!= NULL
);
976 attachments
= e_attachment_store_get_attachments (display
->priv
->attachment_store
);
978 for (link
= attachments
; link
; link
= g_list_next (link
)) {
979 EAttachment
*attachment
= link
->data
;
982 if (!e_attachment_get_can_show (attachment
))
985 flags
= GPOINTER_TO_UINT (g_hash_table_lookup (display
->priv
->attachment_flags
, attachment
));
986 if ((flags
& E_ATTACHMENT_FLAG_VISIBLE
) != 0)
992 g_list_free_full (attachments
, g_object_unref
);
994 view
= e_mail_display_get_attachment_view (display
);
995 attachments
= view
? e_attachment_view_get_selected_attachments (view
) : NULL
;
996 n_selected
= g_list_length (attachments
);
998 if (n_selected
== 1) {
999 EAttachment
*attachment
;
1003 attachment
= attachments
->data
;
1004 mime_type
= e_attachment_dup_mime_type (attachment
);
1005 can_show
= e_attachment_get_can_show (attachment
);
1006 is_image
= can_show
&& mime_type
&& g_ascii_strncasecmp (mime_type
, "image/", 6) == 0;
1008 flags
= GPOINTER_TO_UINT (g_hash_table_lookup (display
->priv
->attachment_flags
, attachment
));
1009 shown
= (flags
& E_ATTACHMENT_FLAG_VISIBLE
) != 0;
1010 zoomed_to_100
= (flags
& E_ATTACHMENT_FLAG_ZOOMED_TO_100
) != 0;
1014 g_list_free_full (attachments
, g_object_unref
);
1016 action
= gtk_action_group_get_action (action_group
, "show");
1017 gtk_action_set_visible (action
, can_show
&& !shown
);
1019 /* Show this action if there are multiple viewable
1020 * attachments, and at least one of them is hidden. */
1021 visible
= (n_shown
+ n_hidden
> 1) && (n_hidden
> 0);
1022 action
= gtk_action_group_get_action (action_group
, "show-all");
1023 gtk_action_set_visible (action
, visible
);
1025 action
= gtk_action_group_get_action (action_group
, "hide");
1026 gtk_action_set_visible (action
, can_show
&& shown
);
1028 /* Show this action if there are multiple viewable
1029 * attachments, and at least one of them is shown. */
1030 visible
= (n_shown
+ n_hidden
> 1) && (n_shown
> 0);
1031 action
= gtk_action_group_get_action (action_group
, "hide-all");
1032 gtk_action_set_visible (action
, visible
);
1034 action
= gtk_action_group_get_action (action_group
, "zoom-to-100");
1035 gtk_action_set_visible (action
, can_show
&& shown
&& is_image
&& !zoomed_to_100
);
1037 action
= gtk_action_group_get_action (action_group
, "zoom-to-window");
1038 gtk_action_set_visible (action
, can_show
&& shown
&& is_image
&& zoomed_to_100
);
1042 mail_display_attachment_menu_deactivate_cb (GtkMenuShell
*menu
,
1045 EMailDisplay
*display
= user_data
;
1047 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
1049 gtk_action_group_set_visible (display
->priv
->attachment_inline_group
, FALSE
);
1051 g_signal_handlers_disconnect_by_func (menu
,
1052 G_CALLBACK (mail_display_attachment_menu_deactivate_cb
), display
);
1056 mail_display_attachment_select_path (EAttachmentView
*view
,
1057 EAttachment
*attachment
)
1061 EAttachmentStore
*store
;
1063 g_return_if_fail (E_IS_ATTACHMENT_VIEW (view
));
1064 g_return_if_fail (E_IS_ATTACHMENT (attachment
));
1066 store
= e_attachment_view_get_store (view
);
1067 g_return_if_fail (e_attachment_store_find_attachment_iter (store
, attachment
, &iter
));
1069 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (store
), &iter
);
1071 e_attachment_view_unselect_all (view
);
1072 e_attachment_view_select_path (view
, path
);
1074 gtk_tree_path_free (path
);
1078 mail_display_attachment_menu_clicked_cb (EWebView
*web_view
,
1079 const gchar
*element_class
,
1080 const gchar
*element_value
,
1081 const GtkAllocation
*element_position
,
1084 EMailDisplay
*display
;
1085 EAttachmentView
*view
;
1086 EAttachment
*attachment
;
1088 g_return_if_fail (E_IS_MAIL_DISPLAY (web_view
));
1089 g_return_if_fail (element_class
!= NULL
);
1090 g_return_if_fail (element_value
!= NULL
);
1091 g_return_if_fail (element_position
!= NULL
);
1093 display
= E_MAIL_DISPLAY (web_view
);
1094 view
= e_mail_display_get_attachment_view (display
);
1095 attachment
= mail_display_ref_attachment_from_element (display
, element_value
);
1097 if (view
&& attachment
) {
1098 GtkWidget
*popup_menu
;
1100 popup_menu
= e_attachment_view_get_popup_menu (view
);
1103 popup_menu
, "deactivate",
1104 G_CALLBACK (mail_display_attachment_menu_deactivate_cb
), display
);
1106 mail_display_attachment_select_path (view
, attachment
);
1107 mail_display_attachment_inline_update_actions (display
);
1108 gtk_action_group_set_visible (display
->priv
->attachment_inline_group
, TRUE
);
1110 e_attachment_view_update_actions (view
);
1111 popup_menu
= e_attachment_view_get_popup_menu (view
);
1113 g_object_set (GTK_MENU (popup_menu
),
1114 "anchor-hints", (GDK_ANCHOR_FLIP_Y
|
1119 gtk_menu_popup_at_rect (GTK_MENU (popup_menu
),
1120 gtk_widget_get_parent_window (GTK_WIDGET (display
)),
1122 GDK_GRAVITY_SOUTH_WEST
,
1123 GDK_GRAVITY_NORTH_WEST
,
1127 g_clear_object (&attachment
);
1131 mail_display_attachment_added_cb (EAttachmentStore
*store
,
1132 EAttachment
*attachment
,
1135 EMailDisplay
*display
= user_data
;
1138 g_return_if_fail (E_IS_ATTACHMENT_STORE (store
));
1139 g_return_if_fail (E_IS_ATTACHMENT (attachment
));
1140 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
1142 flags
= e_attachment_get_initially_shown (attachment
) ? E_ATTACHMENT_FLAG_VISIBLE
: 0;
1144 g_hash_table_insert (display
->priv
->attachment_flags
, attachment
, GUINT_TO_POINTER (flags
));
1148 mail_display_attachment_removed_cb (EAttachmentStore
*store
,
1149 EAttachment
*attachment
,
1152 EMailDisplay
*display
= user_data
;
1154 g_return_if_fail (E_IS_ATTACHMENT_STORE (store
));
1155 g_return_if_fail (E_IS_ATTACHMENT (attachment
));
1156 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
1158 g_hash_table_remove (display
->priv
->attachment_flags
, attachment
);
1161 typedef struct _MailElementExistsData
{
1164 } MailElementExistsData
;
1167 mail_element_exists_cb (GObject
*source_object
,
1168 GAsyncResult
*result
,
1171 GDBusProxy
*web_extension
;
1172 MailElementExistsData
*meed
= user_data
;
1173 gboolean element_exists
= FALSE
;
1174 GVariant
*result_variant
;
1176 GError
*error
= NULL
;
1178 g_return_if_fail (G_IS_DBUS_PROXY (source_object
));
1179 g_return_if_fail (meed
!= NULL
);
1181 web_extension
= G_DBUS_PROXY (source_object
);
1183 result_variant
= g_dbus_proxy_call_finish (web_extension
, result
, &error
);
1184 if (result_variant
) {
1185 g_variant_get (result_variant
, "(bt)", &element_exists
, &page_id
);
1186 g_variant_unref (result_variant
);
1190 e_mail_part_bind_dom_element (
1194 e_mail_part_get_id (meed
->part
));
1196 g_object_unref (meed
->web_view
);
1197 g_object_unref (meed
->part
);
1201 g_dbus_error_strip_remote_error (error
);
1203 e_util_claim_dbus_proxy_call_error (web_extension
, "ElementExists", error
);
1204 g_clear_error (&error
);
1208 mail_parts_bind_dom (EMailDisplay
*display
)
1211 GQueue queue
= G_QUEUE_INIT
;
1213 GDBusProxy
*web_extension
;
1214 gboolean has_attachment
= FALSE
;
1216 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
1218 if (display
->priv
->part_list
== NULL
)
1221 initialize_web_view_colors (display
);
1223 web_view
= E_WEB_VIEW (display
);
1225 web_extension
= e_web_view_get_web_extension_proxy (web_view
);
1229 e_mail_part_list_queue_parts (display
->priv
->part_list
, NULL
, &queue
);
1230 head
= g_queue_peek_head_link (&queue
);
1232 for (link
= head
; link
!= NULL
; link
= g_list_next (link
)) {
1233 MailElementExistsData
*meed
;
1234 EMailPart
*part
= E_MAIL_PART (link
->data
);
1235 const gchar
*part_id
;
1237 part_id
= e_mail_part_get_id (part
);
1239 has_attachment
= has_attachment
|| E_IS_MAIL_PART_ATTACHMENT (part
);
1241 e_mail_part_web_view_loaded (part
, web_view
);
1243 meed
= g_new0 (MailElementExistsData
, 1);
1244 meed
->web_view
= g_object_ref (web_view
);
1245 meed
->part
= g_object_ref (part
);
1252 webkit_web_view_get_page_id (
1253 WEBKIT_WEB_VIEW (display
)),
1255 G_DBUS_CALL_FLAGS_NONE
,
1258 mail_element_exists_cb
,
1262 while (!g_queue_is_empty (&queue
))
1263 g_object_unref (g_queue_pop_head (&queue
));
1265 if (has_attachment
) {
1266 e_web_view_register_element_clicked (web_view
, "attachment-expander",
1267 mail_display_attachment_expander_clicked_cb
, NULL
);
1268 e_web_view_register_element_clicked (web_view
, "attachment-menu",
1269 mail_display_attachment_menu_clicked_cb
, NULL
);
1274 mail_display_load_changed_cb (WebKitWebView
*wk_web_view
,
1275 WebKitLoadEvent load_event
,
1278 EMailDisplay
*display
;
1280 g_return_if_fail (E_IS_MAIL_DISPLAY (wk_web_view
));
1282 display
= E_MAIL_DISPLAY (wk_web_view
);
1284 if (load_event
== WEBKIT_LOAD_STARTED
) {
1285 e_mail_display_cleanup_skipped_uris (display
);
1286 e_attachment_store_remove_all (display
->priv
->attachment_store
);
1290 if (load_event
== WEBKIT_LOAD_FINISHED
) {
1291 setup_dom_bindings (display
);
1292 mail_parts_bind_dom (display
);
1297 mail_display_set_property (GObject
*object
,
1299 const GValue
*value
,
1302 switch (property_id
) {
1303 case PROP_HEADERS_COLLAPSABLE
:
1304 e_mail_display_set_headers_collapsable (
1305 E_MAIL_DISPLAY (object
),
1306 g_value_get_boolean (value
));
1309 case PROP_HEADERS_COLLAPSED
:
1310 e_mail_display_set_headers_collapsed (
1311 E_MAIL_DISPLAY (object
),
1312 g_value_get_boolean (value
));
1316 e_mail_display_set_mode (
1317 E_MAIL_DISPLAY (object
),
1318 g_value_get_enum (value
));
1321 case PROP_PART_LIST
:
1322 e_mail_display_set_part_list (
1323 E_MAIL_DISPLAY (object
),
1324 g_value_get_pointer (value
));
1327 case PROP_REMOTE_CONTENT
:
1328 e_mail_display_set_remote_content (
1329 E_MAIL_DISPLAY (object
),
1330 g_value_get_object (value
));
1334 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1338 mail_display_get_property (GObject
*object
,
1343 switch (property_id
) {
1344 case PROP_ATTACHMENT_STORE
:
1345 g_value_set_object (
1347 e_mail_display_get_attachment_store (
1348 E_MAIL_DISPLAY (object
)));
1351 case PROP_ATTACHMENT_VIEW
:
1352 g_value_set_object (
1354 e_mail_display_get_attachment_view (
1355 E_MAIL_DISPLAY (object
)));
1358 case PROP_FORMATTER
:
1359 g_value_set_object (
1361 e_mail_display_get_formatter (
1362 E_MAIL_DISPLAY (object
)));
1365 case PROP_HEADERS_COLLAPSABLE
:
1366 g_value_set_boolean (
1368 e_mail_display_get_headers_collapsable (
1369 E_MAIL_DISPLAY (object
)));
1372 case PROP_HEADERS_COLLAPSED
:
1373 g_value_set_boolean (
1375 e_mail_display_get_headers_collapsed (
1376 E_MAIL_DISPLAY (object
)));
1382 e_mail_display_get_mode (
1383 E_MAIL_DISPLAY (object
)));
1386 case PROP_PART_LIST
:
1387 g_value_set_pointer (
1389 e_mail_display_get_part_list (
1390 E_MAIL_DISPLAY (object
)));
1393 case PROP_REMOTE_CONTENT
:
1394 g_value_take_object (
1396 e_mail_display_ref_remote_content (
1397 E_MAIL_DISPLAY (object
)));
1401 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1405 mail_display_dispose (GObject
*object
)
1407 EMailDisplayPrivate
*priv
;
1409 priv
= E_MAIL_DISPLAY_GET_PRIVATE (object
);
1411 if (priv
->scheduled_reload
> 0) {
1412 g_source_remove (priv
->scheduled_reload
);
1413 priv
->scheduled_reload
= 0;
1416 if (priv
->settings
!= NULL
) {
1417 g_signal_handlers_disconnect_matched (
1418 priv
->settings
, G_SIGNAL_MATCH_DATA
,
1419 0, 0, NULL
, NULL
, object
);
1422 if (priv
->web_extension_headers_collapsed_signal_id
> 0) {
1423 GDBusProxy
*web_extension
= e_web_view_get_web_extension_proxy (E_WEB_VIEW (object
));
1425 if (web_extension
!= NULL
) {
1426 g_dbus_connection_signal_unsubscribe (
1427 g_dbus_proxy_get_connection (web_extension
),
1428 priv
->web_extension_headers_collapsed_signal_id
);
1430 priv
->web_extension_headers_collapsed_signal_id
= 0;
1433 if (priv
->web_extension_mail_part_appeared_signal_id
> 0) {
1434 GDBusProxy
*web_extension
= e_web_view_get_web_extension_proxy (E_WEB_VIEW (object
));
1436 if (web_extension
!= NULL
) {
1437 g_dbus_connection_signal_unsubscribe (
1438 g_dbus_proxy_get_connection (web_extension
),
1439 priv
->web_extension_mail_part_appeared_signal_id
);
1441 priv
->web_extension_mail_part_appeared_signal_id
= 0;
1444 if (priv
->attachment_store
) {
1445 /* To have called the mail_display_attachment_removed_cb() before it's disconnected */
1446 e_attachment_store_remove_all (priv
->attachment_store
);
1448 g_signal_handlers_disconnect_by_func (priv
->attachment_store
,
1449 G_CALLBACK (mail_display_attachment_added_cb
), object
);
1451 g_signal_handlers_disconnect_by_func (priv
->attachment_store
,
1452 G_CALLBACK (mail_display_attachment_removed_cb
), object
);
1455 g_clear_object (&priv
->part_list
);
1456 g_clear_object (&priv
->formatter
);
1457 g_clear_object (&priv
->settings
);
1458 g_clear_object (&priv
->attachment_store
);
1459 g_clear_object (&priv
->attachment_view
);
1460 g_clear_object (&priv
->attachment_inline_group
);
1462 /* Chain up to parent's dispose() method. */
1463 G_OBJECT_CLASS (e_mail_display_parent_class
)->dispose (object
);
1467 mail_display_finalize (GObject
*object
)
1469 EMailDisplayPrivate
*priv
;
1471 priv
= E_MAIL_DISPLAY_GET_PRIVATE (object
);
1473 if (priv
->old_settings
) {
1474 g_hash_table_destroy (priv
->old_settings
);
1475 priv
->old_settings
= NULL
;
1478 g_mutex_lock (&priv
->remote_content_lock
);
1479 if (priv
->skipped_remote_content_sites
) {
1480 g_hash_table_destroy (priv
->skipped_remote_content_sites
);
1481 priv
->skipped_remote_content_sites
= NULL
;
1484 g_hash_table_destroy (priv
->attachment_flags
);
1485 g_clear_object (&priv
->remote_content
);
1486 g_mutex_unlock (&priv
->remote_content_lock
);
1487 g_mutex_clear (&priv
->remote_content_lock
);
1489 /* Chain up to parent's finalize() method. */
1490 G_OBJECT_CLASS (e_mail_display_parent_class
)->finalize (object
);
1494 mail_display_get_font_settings (GSettings
*settings
,
1495 PangoFontDescription
**monospace
,
1496 PangoFontDescription
**variable
)
1498 gboolean use_custom_font
;
1499 gchar
*monospace_font
;
1500 gchar
*variable_font
;
1502 use_custom_font
= g_settings_get_boolean (settings
, "use-custom-font");
1504 if (!use_custom_font
) {
1512 monospace_font
= g_settings_get_string (settings
, "monospace-font");
1513 variable_font
= g_settings_get_string (settings
, "variable-width-font");
1516 *monospace
= (monospace_font
!= NULL
) ? pango_font_description_from_string (monospace_font
) : NULL
;
1518 *variable
= (variable_font
!= NULL
) ? pango_font_description_from_string (variable_font
) : NULL
;
1520 g_free (monospace_font
);
1521 g_free (variable_font
);
1525 mail_display_set_fonts (EWebView
*web_view
,
1526 PangoFontDescription
**monospace
,
1527 PangoFontDescription
**variable
)
1529 EMailDisplay
*display
= E_MAIL_DISPLAY (web_view
);
1531 mail_display_get_font_settings (display
->priv
->settings
, monospace
, variable
);
1535 mail_display_web_view_initialize (WebKitWebView
*web_view
)
1537 WebKitSettings
*webkit_settings
;
1539 webkit_settings
= webkit_web_view_get_settings (web_view
);
1541 g_object_set (webkit_settings
,
1542 "enable-frame-flattening", TRUE
,
1547 mail_display_constructed (GObject
*object
)
1549 EContentRequest
*content_request
;
1551 EMailDisplay
*display
;
1552 GtkUIManager
*ui_manager
;
1554 e_extensible_load_extensions (E_EXTENSIBLE (object
));
1556 /* Chain up to parent's constructed() method. */
1557 G_OBJECT_CLASS (e_mail_display_parent_class
)->constructed (object
);
1559 mail_display_web_view_initialize (WEBKIT_WEB_VIEW (object
));
1561 display
= E_MAIL_DISPLAY (object
);
1562 web_view
= E_WEB_VIEW (object
);
1564 e_web_view_update_fonts (web_view
);
1566 content_request
= e_http_request_new ();
1567 e_web_view_register_content_request_for_scheme (web_view
, "evo-http", content_request
);
1568 e_web_view_register_content_request_for_scheme (web_view
, "evo-https", content_request
);
1569 g_object_unref (content_request
);
1571 content_request
= e_mail_request_new ();
1572 e_web_view_register_content_request_for_scheme (web_view
, "mail", content_request
);
1573 g_object_unref (content_request
);
1575 content_request
= e_cid_request_new ();
1576 e_web_view_register_content_request_for_scheme (web_view
, "cid", content_request
);
1577 g_object_unref (content_request
);
1579 display
->priv
->attachment_view
= g_object_ref_sink (e_attachment_bar_new (display
->priv
->attachment_store
));
1581 ui_manager
= e_attachment_view_get_ui_manager (display
->priv
->attachment_view
);
1583 GError
*error
= NULL
;
1585 gtk_ui_manager_insert_action_group (ui_manager
, display
->priv
->attachment_inline_group
, -1);
1587 display
->priv
->attachment_inline_ui_id
= gtk_ui_manager_add_ui_from_string (ui_manager
,
1588 attachment_popup_ui
, -1, &error
);
1591 g_warning ("%s: Failed to read attachment_popup_ui: %s", G_STRFUNC
, error
->message
);
1592 g_clear_error (&error
);
1598 mail_display_realize (GtkWidget
*widget
)
1600 /* Chain up to parent's realize() method. */
1601 GTK_WIDGET_CLASS (e_mail_display_parent_class
)->realize (widget
);
1603 mail_display_update_formatter_colors (E_MAIL_DISPLAY (widget
));
1607 mail_display_style_updated (GtkWidget
*widget
)
1609 EMailDisplay
*display
= E_MAIL_DISPLAY (widget
);
1611 mail_display_update_formatter_colors (display
);
1613 /* Chain up to parent's style_updated() method. */
1614 GTK_WIDGET_CLASS (e_mail_display_parent_class
)->
1615 style_updated (widget
);
1619 mail_display_button_press_event (GtkWidget
*widget
,
1620 GdkEventButton
*event
)
1622 if (event
->button
== 3) {
1623 EWebView
*web_view
= E_WEB_VIEW (widget
);
1624 gchar
*popup_document_uri
;
1627 popup_document_uri
= e_web_view_get_document_uri_from_point (web_view
, event
->x
, event
->y
);
1629 list
= e_extensible_list_extensions (
1630 E_EXTENSIBLE (web_view
), E_TYPE_EXTENSION
);
1631 for (link
= list
; link
!= NULL
; link
= g_list_next (link
)) {
1632 EExtension
*extension
= link
->data
;
1634 if (!E_IS_MAIL_DISPLAY_POPUP_EXTENSION (extension
))
1637 e_mail_display_popup_extension_update_actions (
1638 E_MAIL_DISPLAY_POPUP_EXTENSION (extension
), popup_document_uri
);
1642 g_free (popup_document_uri
);
1645 /* Chain up to parent's button_press_event() method. */
1646 return GTK_WIDGET_CLASS (e_mail_display_parent_class
)->
1647 button_press_event (widget
, event
);
1652 mail_display_image_exists_in_cache (const gchar
*image_uri
)
1656 gboolean exists
= FALSE
;
1658 if (!emd_global_http_cache
)
1661 hash
= g_compute_checksum_for_string (G_CHECKSUM_MD5
, image_uri
, -1);
1662 filename
= camel_data_cache_get_filename (
1663 emd_global_http_cache
, "http", hash
);
1665 if (filename
!= NULL
) {
1668 exists
= g_file_test (filename
, G_FILE_TEST_EXISTS
);
1669 if (exists
&& g_stat (filename
, &st
) == 0) {
1670 exists
= st
.st_size
!= 0;
1683 mail_display_uri_requested_cb (EWebView
*web_view
,
1685 gchar
**redirect_to_uri
)
1687 EMailDisplay
*display
;
1688 EMailPartList
*part_list
;
1689 gboolean uri_is_http
;
1691 display
= E_MAIL_DISPLAY (web_view
);
1692 part_list
= e_mail_display_get_part_list (display
);
1694 if (part_list
== NULL
)
1698 g_str_has_prefix (uri
, "http:") ||
1699 g_str_has_prefix (uri
, "https:") ||
1700 g_str_has_prefix (uri
, "evo-http:") ||
1701 g_str_has_prefix (uri
, "evo-https:");
1703 /* Redirect http(s) request to evo-http(s) protocol.
1704 * See EMailRequest for further details about this. */
1706 CamelFolder
*folder
;
1707 const gchar
*message_uid
;
1708 gchar
*new_uri
, *mail_uri
, *enc
;
1711 gboolean can_download_uri
;
1712 EImageLoadingPolicy image_policy
;
1714 can_download_uri
= e_mail_display_can_download_uri (display
, uri
);
1715 if (!can_download_uri
) {
1716 /* Check Evolution's cache */
1717 can_download_uri
= mail_display_image_exists_in_cache (
1718 uri
+ (g_str_has_prefix (uri
, "evo-") ? 4 : 0));
1721 /* If the URI is not cached and we are not allowed to load it
1722 * then redirect to invalid URI, so that webkit would display
1723 * a native placeholder for it. */
1724 image_policy
= e_mail_formatter_get_image_loading_policy (
1725 display
->priv
->formatter
);
1726 if (!can_download_uri
&& !display
->priv
->force_image_load
&&
1727 (image_policy
== E_IMAGE_LOADING_POLICY_NEVER
)) {
1728 e_mail_display_claim_skipped_uri (display
, uri
);
1729 g_free (*redirect_to_uri
);
1730 *redirect_to_uri
= g_strdup ("");
1734 folder
= e_mail_part_list_get_folder (part_list
);
1735 message_uid
= e_mail_part_list_get_message_uid (part_list
);
1737 if (g_str_has_prefix (uri
, "evo-")) {
1738 soup_uri
= soup_uri_new (uri
);
1740 new_uri
= g_strconcat ("evo-", uri
, NULL
);
1741 soup_uri
= soup_uri_new (new_uri
);
1746 mail_uri
= e_mail_part_build_uri (
1747 folder
, message_uid
, NULL
, NULL
);
1749 if (soup_uri
->query
)
1750 query
= soup_form_decode (soup_uri
->query
);
1752 query
= g_hash_table_new_full (
1753 g_str_hash
, g_str_equal
,
1755 enc
= soup_uri_encode (mail_uri
, NULL
);
1756 g_hash_table_insert (query
, g_strdup ("__evo-mail"), enc
);
1758 /* Required, because soup_uri_set_query_from_form() can change
1759 order of arguments, then the URL checksum doesn't match. */
1760 g_hash_table_insert (query
, g_strdup ("__evo-original-uri"), g_strdup (uri
));
1762 if (display
->priv
->force_image_load
|| can_download_uri
) {
1763 g_hash_table_insert (
1765 g_strdup ("__evo-load-images"),
1767 } else if (image_policy
!= E_IMAGE_LOADING_POLICY_ALWAYS
) {
1768 e_mail_display_claim_skipped_uri (display
, uri
);
1773 soup_uri_set_query_from_form (soup_uri
, query
);
1775 new_uri
= soup_uri_to_string (soup_uri
, FALSE
);
1777 soup_uri_free (soup_uri
);
1778 g_hash_table_unref (query
);
1780 g_free (*redirect_to_uri
);
1781 *redirect_to_uri
= new_uri
;
1785 static CamelMimePart
*
1786 camel_mime_part_from_cid (EMailDisplay
*display
,
1789 EMailPartList
*part_list
;
1790 CamelMimeMessage
*message
;
1791 CamelMimePart
*mime_part
;
1793 if (!g_str_has_prefix (uri
, "cid:"))
1796 part_list
= e_mail_display_get_part_list (display
);
1800 message
= e_mail_part_list_get_message (part_list
);
1804 mime_part
= camel_mime_message_get_part_by_content_id (
1811 mail_display_suggest_filename (EWebView
*web_view
,
1814 EMailDisplay
*display
;
1815 CamelMimePart
*mime_part
;
1817 /* Note, this assumes the URI comes
1818 * from the currently loaded message. */
1819 display
= E_MAIL_DISPLAY (web_view
);
1821 mime_part
= camel_mime_part_from_cid (display
, uri
);
1824 return g_strdup (camel_mime_part_get_filename (mime_part
));
1826 /* Chain up to parent's suggest_filename() method. */
1827 return E_WEB_VIEW_CLASS (e_mail_display_parent_class
)->
1828 suggest_filename (web_view
, uri
);
1832 mail_display_save_part_for_drop (CamelMimePart
*mime_part
,
1833 GtkSelectionData
*data
)
1835 gchar
*tmp
, *path
, *filename
;
1836 const gchar
*part_filename
;
1837 CamelDataWrapper
*dw
;
1839 g_return_if_fail (CAMEL_IS_MIME_PART (mime_part
));
1840 g_return_if_fail (data
!= NULL
);
1842 tmp
= g_strdup_printf (PACKAGE
"-%s-XXXXXX", g_get_user_name ());
1843 path
= e_mkdtemp (tmp
);
1846 g_return_if_fail (path
!= NULL
);
1848 part_filename
= camel_mime_part_get_filename (mime_part
);
1849 if (!part_filename
|| !*part_filename
) {
1850 CamelDataWrapper
*content
;
1852 content
= camel_medium_get_content (CAMEL_MEDIUM (mime_part
));
1854 if (CAMEL_IS_MIME_MESSAGE (content
))
1855 part_filename
= camel_mime_message_get_subject (CAMEL_MIME_MESSAGE (content
));
1858 if (!part_filename
|| !*part_filename
)
1859 part_filename
= "mail-part";
1861 tmp
= g_strdup (part_filename
);
1862 e_filename_make_safe (tmp
);
1864 filename
= g_build_filename (path
, tmp
, NULL
);
1867 dw
= camel_medium_get_content (CAMEL_MEDIUM (mime_part
));
1868 g_warn_if_fail (dw
);
1871 CamelStream
*stream
;
1873 stream
= camel_stream_fs_new_with_name (filename
, O_CREAT
| O_TRUNC
| O_WRONLY
, 0666, NULL
);
1875 if (camel_data_wrapper_decode_to_stream_sync (dw
, stream
, NULL
, NULL
)) {
1876 tmp
= g_filename_to_uri (filename
, NULL
, NULL
);
1878 gtk_selection_data_set (
1880 gtk_selection_data_get_data_type (data
),
1881 gtk_selection_data_get_format (data
),
1882 (const guchar
*) tmp
, strlen (tmp
));
1887 camel_stream_close (stream
, NULL
, NULL
);
1888 g_object_unref (stream
);
1897 mail_display_drag_data_get (GtkWidget
*widget
,
1898 GdkDragContext
*context
,
1899 GtkSelectionData
*data
,
1902 EMailDisplay
*display
)
1904 CamelDataWrapper
*dw
;
1905 CamelMimePart
*mime_part
;
1906 CamelStream
*stream
;
1907 gchar
*src
, *base64_encoded
, *mime_type
, *uri
;
1908 const gchar
*filename
;
1909 const guchar
*data_from_webkit
;
1911 GByteArray
*byte_array
;
1913 data_from_webkit
= gtk_selection_data_get_data (data
);
1914 length
= gtk_selection_data_get_length (data
);
1916 uri
= g_strndup ((const gchar
*) data_from_webkit
, length
);
1918 mime_part
= camel_mime_part_from_cid (display
, uri
);
1920 if (!mime_part
&& g_str_has_prefix (uri
, "mail:")) {
1922 const gchar
*soup_query
;
1924 soup_uri
= soup_uri_new (uri
);
1926 soup_query
= soup_uri_get_query (soup_uri
);
1929 const gchar
*part_id_raw
;
1931 query
= soup_form_decode (soup_query
);
1932 part_id_raw
= query
? g_hash_table_lookup (query
, "part_id") : NULL
;
1933 if (part_id_raw
&& *part_id_raw
) {
1934 EMailPartList
*part_list
;
1935 EMailPart
*mail_part
;
1937 part_list
= e_mail_display_get_part_list (display
);
1939 gchar
*part_id
= soup_uri_decode (part_id_raw
);
1941 mail_part
= e_mail_part_list_ref_part (part_list
, part_id
);
1945 CamelMimePart
*part
;
1947 part
= e_mail_part_ref_mime_part (mail_part
);
1949 mail_display_save_part_for_drop (part
, data
);
1952 g_clear_object (&part
);
1953 g_object_unref (mail_part
);
1959 g_hash_table_unref (query
);
1962 soup_uri_free (soup_uri
);
1969 stream
= camel_stream_mem_new ();
1970 dw
= camel_medium_get_content (CAMEL_MEDIUM (mime_part
));
1971 g_return_if_fail (dw
);
1973 mime_type
= camel_data_wrapper_get_mime_type (dw
);
1974 camel_data_wrapper_decode_to_stream_sync (dw
, stream
, NULL
, NULL
);
1975 camel_stream_close (stream
, NULL
, NULL
);
1977 byte_array
= camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (stream
));
1979 if (!byte_array
->data
) {
1980 g_object_unref (stream
);
1984 base64_encoded
= g_base64_encode ((const guchar
*) byte_array
->data
, byte_array
->len
);
1986 filename
= camel_mime_part_get_filename (mime_part
);
1987 /* Insert filename before base64 data */
1988 src
= g_strconcat (filename
, ";data:", mime_type
, ";base64,", base64_encoded
, NULL
);
1990 gtk_selection_data_set (
1992 gtk_selection_data_get_data_type (data
),
1993 gtk_selection_data_get_format (data
),
1994 (const guchar
*) src
, strlen (src
));
1997 g_free (base64_encoded
);
1999 g_object_unref (stream
);
2005 e_mail_display_test_change_and_update_fonts_cb (EMailDisplay
*mail_display
,
2007 GSettings
*settings
)
2009 GVariant
*new_value
, *old_value
;
2011 new_value
= g_settings_get_value (settings
, key
);
2012 old_value
= g_hash_table_lookup (mail_display
->priv
->old_settings
, key
);
2014 if (!new_value
|| !old_value
|| !g_variant_equal (new_value
, old_value
)) {
2016 g_hash_table_insert (mail_display
->priv
->old_settings
, g_strdup (key
), new_value
);
2018 g_hash_table_remove (mail_display
->priv
->old_settings
, key
);
2020 e_web_view_update_fonts (E_WEB_VIEW (mail_display
));
2021 } else if (new_value
) {
2022 g_variant_unref (new_value
);
2027 mail_display_web_process_crashed_cb (EMailDisplay
*display
)
2029 EAlertSink
*alert_sink
;
2031 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2033 /* Cannot use the EWebView, because it places the alerts inside itself */
2034 alert_sink
= e_shell_utils_find_alternate_alert_sink (GTK_WIDGET (display
));
2036 e_alert_submit (alert_sink
, "mail:webkit-web-process-crashed", NULL
);
2040 e_mail_display_class_init (EMailDisplayClass
*class)
2042 GObjectClass
*object_class
;
2043 EWebViewClass
*web_view_class
;
2044 GtkWidgetClass
*widget_class
;
2046 g_type_class_add_private (class, sizeof (EMailDisplayPrivate
));
2048 object_class
= G_OBJECT_CLASS (class);
2049 object_class
->constructed
= mail_display_constructed
;
2050 object_class
->set_property
= mail_display_set_property
;
2051 object_class
->get_property
= mail_display_get_property
;
2052 object_class
->dispose
= mail_display_dispose
;
2053 object_class
->finalize
= mail_display_finalize
;
2055 widget_class
= GTK_WIDGET_CLASS (class);
2056 widget_class
->realize
= mail_display_realize
;
2057 widget_class
->style_updated
= mail_display_style_updated
;
2058 widget_class
->button_press_event
= mail_display_button_press_event
;
2060 web_view_class
= E_WEB_VIEW_CLASS (class);
2061 web_view_class
->suggest_filename
= mail_display_suggest_filename
;
2062 web_view_class
->set_fonts
= mail_display_set_fonts
;
2064 g_object_class_install_property (
2066 PROP_ATTACHMENT_STORE
,
2067 g_param_spec_object (
2071 E_TYPE_ATTACHMENT_STORE
,
2073 G_PARAM_STATIC_STRINGS
));
2075 g_object_class_install_property (
2077 PROP_ATTACHMENT_VIEW
,
2078 g_param_spec_object (
2082 E_TYPE_ATTACHMENT_VIEW
,
2084 G_PARAM_STATIC_STRINGS
));
2086 g_object_class_install_property (
2089 g_param_spec_pointer (
2094 G_PARAM_STATIC_STRINGS
));
2096 g_object_class_install_property (
2098 PROP_HEADERS_COLLAPSABLE
,
2099 g_param_spec_boolean (
2100 "headers-collapsable",
2101 "Headers Collapsable",
2105 G_PARAM_STATIC_STRINGS
));
2107 g_object_class_install_property (
2109 PROP_HEADERS_COLLAPSED
,
2110 g_param_spec_boolean (
2111 "headers-collapsed",
2112 "Headers Collapsed",
2116 G_PARAM_STATIC_STRINGS
));
2118 g_object_class_install_property (
2125 E_TYPE_MAIL_FORMATTER_MODE
,
2126 E_MAIL_FORMATTER_MODE_NORMAL
,
2128 G_PARAM_STATIC_STRINGS
));
2130 g_object_class_install_property (
2133 g_param_spec_pointer (
2138 G_PARAM_STATIC_STRINGS
));
2140 g_object_class_install_property (
2142 PROP_REMOTE_CONTENT
,
2143 g_param_spec_object (
2145 "Mail Remote Content",
2147 E_TYPE_MAIL_REMOTE_CONTENT
,
2149 G_PARAM_STATIC_STRINGS
));
2153 e_mail_display_init (EMailDisplay
*display
)
2155 GtkUIManager
*ui_manager
;
2156 GtkActionGroup
*actions
;
2158 display
->priv
= E_MAIL_DISPLAY_GET_PRIVATE (display
);
2160 display
->priv
->attachment_store
= E_ATTACHMENT_STORE (e_attachment_store_new ());
2161 display
->priv
->attachment_flags
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
2162 display
->priv
->attachment_inline_group
= gtk_action_group_new ("e-mail-display-attachment-inline");
2164 gtk_action_group_add_actions (
2165 display
->priv
->attachment_inline_group
, attachment_inline_entries
,
2166 G_N_ELEMENTS (attachment_inline_entries
), display
);
2167 gtk_action_group_set_visible (display
->priv
->attachment_inline_group
, FALSE
);
2169 g_signal_connect (display
->priv
->attachment_store
, "attachment-added",
2170 G_CALLBACK (mail_display_attachment_added_cb
), display
);
2171 g_signal_connect (display
->priv
->attachment_store
, "attachment-removed",
2172 G_CALLBACK (mail_display_attachment_removed_cb
), display
);
2174 display
->priv
->old_settings
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_variant_unref
);
2176 /* Set invalid mode so that MODE property initialization is run
2177 * completely (see e_mail_display_set_mode) */
2178 display
->priv
->mode
= E_MAIL_FORMATTER_MODE_INVALID
;
2179 e_mail_display_set_mode (display
, E_MAIL_FORMATTER_MODE_NORMAL
);
2180 display
->priv
->force_image_load
= FALSE
;
2181 display
->priv
->scheduled_reload
= 0;
2184 display
, "web-process-crashed",
2185 G_CALLBACK (mail_display_web_process_crashed_cb
), NULL
);
2188 display
, "decide-policy",
2189 G_CALLBACK (decide_policy_cb
), NULL
);
2192 display
, "process-mailto",
2193 G_CALLBACK (mail_display_process_mailto
), NULL
);
2195 g_signal_connect_after (
2196 display
, "drag-data-get",
2197 G_CALLBACK (mail_display_drag_data_get
), display
);
2199 display
->priv
->settings
= e_util_ref_settings ("org.gnome.evolution.mail");
2200 g_signal_connect_swapped (
2201 display
->priv
->settings
, "changed::monospace-font",
2202 G_CALLBACK (e_mail_display_test_change_and_update_fonts_cb
), display
);
2203 g_signal_connect_swapped (
2204 display
->priv
->settings
, "changed::variable-width-font",
2205 G_CALLBACK (e_mail_display_test_change_and_update_fonts_cb
), display
);
2206 g_signal_connect_swapped (
2207 display
->priv
->settings
, "changed::use-custom-font",
2208 G_CALLBACK (e_mail_display_test_change_and_update_fonts_cb
), display
);
2211 display
, "load-changed",
2212 G_CALLBACK (mail_display_load_changed_cb
), NULL
);
2214 actions
= e_web_view_get_action_group (E_WEB_VIEW (display
), "mailto");
2215 gtk_action_group_add_actions (
2216 actions
, mailto_entries
,
2217 G_N_ELEMENTS (mailto_entries
), display
);
2218 ui_manager
= e_web_view_get_ui_manager (E_WEB_VIEW (display
));
2219 gtk_ui_manager_add_ui_from_string (ui_manager
, ui
, -1, NULL
);
2221 g_mutex_init (&display
->priv
->remote_content_lock
);
2222 display
->priv
->remote_content
= NULL
;
2223 display
->priv
->skipped_remote_content_sites
= g_hash_table_new_full (camel_strcase_hash
, camel_strcase_equal
, g_free
, NULL
);
2225 g_signal_connect (display
, "uri-requested", G_CALLBACK (mail_display_uri_requested_cb
), NULL
);
2227 if (emd_global_http_cache
== NULL
) {
2228 const gchar
*user_cache_dir
;
2229 GError
*error
= NULL
;
2231 user_cache_dir
= e_get_user_cache_dir ();
2232 emd_global_http_cache
= camel_data_cache_new (user_cache_dir
, &error
);
2234 if (emd_global_http_cache
) {
2235 /* cache expiry - 2 hour access, 1 day max */
2236 camel_data_cache_set_expire_age (
2237 emd_global_http_cache
, 24 * 60 * 60);
2238 camel_data_cache_set_expire_access (
2239 emd_global_http_cache
, 2 * 60 * 60);
2242 E_ALERT_SINK (display
), "mail:folder-open",
2243 error
? error
->message
: _("Unknown error"), NULL
);
2244 g_clear_error (&error
);
2250 e_mail_display_update_colors (EMailDisplay
*display
,
2251 GParamSpec
*param_spec
,
2252 EMailFormatter
*formatter
)
2254 GdkRGBA
*color
= NULL
;
2257 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2258 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter
));
2260 g_object_get (formatter
, param_spec
->name
, &color
, NULL
);
2262 color_value
= g_strdup_printf ("#%06x", e_rgba_to_value (color
));
2264 add_color_css_rule_for_web_view (
2265 E_WEB_VIEW (display
),
2269 gdk_rgba_free (color
);
2270 g_free (color_value
);
2274 e_mail_display_claim_attachment (EMailFormatter
*formatter
,
2275 EAttachment
*attachment
,
2278 EMailDisplay
*display
= user_data
;
2281 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter
));
2282 g_return_if_fail (E_IS_ATTACHMENT (attachment
));
2283 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2285 attachments
= e_attachment_store_get_attachments (display
->priv
->attachment_store
);
2287 if (!g_list_find (attachments
, attachment
)) {
2288 e_attachment_store_add_attachment (display
->priv
->attachment_store
, attachment
);
2290 if (e_attachment_is_mail_note (attachment
)) {
2291 CamelFolder
*folder
;
2292 const gchar
*message_uid
;
2294 folder
= e_mail_part_list_get_folder (display
->priv
->part_list
);
2295 message_uid
= e_mail_part_list_get_message_uid (display
->priv
->part_list
);
2297 if (folder
&& message_uid
) {
2298 CamelMessageInfo
*info
;
2300 info
= camel_folder_get_message_info (folder
, message_uid
);
2302 if (!camel_message_info_get_user_flag (info
, E_MAIL_NOTES_USER_FLAG
))
2303 camel_message_info_set_user_flag (info
, E_MAIL_NOTES_USER_FLAG
, TRUE
);
2304 g_clear_object (&info
);
2310 g_list_free_full (attachments
, g_object_unref
);
2314 e_mail_display_new (EMailRemoteContent
*remote_content
)
2316 return g_object_new (E_TYPE_MAIL_DISPLAY
,
2317 "remote-content", remote_content
,
2322 e_mail_display_get_attachment_store (EMailDisplay
*display
)
2324 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), NULL
);
2326 return display
->priv
->attachment_store
;
2330 e_mail_display_get_attachment_view (EMailDisplay
*display
)
2332 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), NULL
);
2334 return display
->priv
->attachment_view
;
2338 e_mail_display_get_mode (EMailDisplay
*display
)
2340 g_return_val_if_fail (
2341 E_IS_MAIL_DISPLAY (display
),
2342 E_MAIL_FORMATTER_MODE_INVALID
);
2344 return display
->priv
->mode
;
2348 e_mail_display_set_mode (EMailDisplay
*display
,
2349 EMailFormatterMode mode
)
2351 EMailFormatter
*formatter
;
2353 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2355 if (display
->priv
->mode
== mode
)
2358 display
->priv
->mode
= mode
;
2360 if (display
->priv
->mode
== E_MAIL_FORMATTER_MODE_PRINTING
)
2361 formatter
= e_mail_formatter_print_new ();
2363 formatter
= e_mail_formatter_new ();
2365 g_clear_object (&display
->priv
->formatter
);
2366 display
->priv
->formatter
= formatter
;
2367 mail_display_update_formatter_colors (display
);
2369 e_signal_connect_notify (
2370 formatter
, "notify::image-loading-policy",
2371 G_CALLBACK (formatter_image_loading_policy_changed_cb
),
2374 e_signal_connect_notify_object (
2375 formatter
, "notify::charset",
2376 G_CALLBACK (e_mail_display_reload
), display
, G_CONNECT_SWAPPED
);
2378 e_signal_connect_notify_object (
2379 formatter
, "notify::image-loading-policy",
2380 G_CALLBACK (e_mail_display_reload
), display
, G_CONNECT_SWAPPED
);
2382 e_signal_connect_notify_object (
2383 formatter
, "notify::mark-citations",
2384 G_CALLBACK (e_mail_display_reload
), display
, G_CONNECT_SWAPPED
);
2386 e_signal_connect_notify_object (
2387 formatter
, "notify::show-sender-photo",
2388 G_CALLBACK (e_mail_display_reload
), display
, G_CONNECT_SWAPPED
);
2390 e_signal_connect_notify_object (
2391 formatter
, "notify::show-real-date",
2392 G_CALLBACK (e_mail_display_reload
), display
, G_CONNECT_SWAPPED
);
2394 e_signal_connect_notify_object (
2395 formatter
, "notify::animate-images",
2396 G_CALLBACK (e_mail_display_reload
), display
, G_CONNECT_SWAPPED
);
2398 e_signal_connect_notify_object (
2399 formatter
, "notify::body-color",
2400 G_CALLBACK (e_mail_display_update_colors
), display
, G_CONNECT_SWAPPED
);
2402 e_signal_connect_notify_object (
2403 formatter
, "notify::citation-color",
2404 G_CALLBACK (e_mail_display_update_colors
), display
, G_CONNECT_SWAPPED
);
2406 e_signal_connect_notify_object (
2407 formatter
, "notify::frame-color",
2408 G_CALLBACK (e_mail_display_update_colors
), display
, G_CONNECT_SWAPPED
);
2410 e_signal_connect_notify_object (
2411 formatter
, "notify::header-color",
2412 G_CALLBACK (e_mail_display_update_colors
), display
, G_CONNECT_SWAPPED
);
2414 g_object_connect (formatter
,
2415 "swapped-object-signal::need-redraw",
2416 G_CALLBACK (e_mail_display_reload
), display
,
2419 g_signal_connect (formatter
, "claim-attachment", G_CALLBACK (e_mail_display_claim_attachment
), display
);
2421 e_mail_display_reload (display
);
2423 g_object_notify (G_OBJECT (display
), "mode");
2427 e_mail_display_get_formatter (EMailDisplay
*display
)
2429 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), NULL
);
2431 return display
->priv
->formatter
;
2435 e_mail_display_get_part_list (EMailDisplay
*display
)
2437 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), NULL
);
2439 return display
->priv
->part_list
;
2443 e_mail_display_set_part_list (EMailDisplay
*display
,
2444 EMailPartList
*part_list
)
2446 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2448 if (display
->priv
->part_list
== part_list
)
2451 if (part_list
!= NULL
) {
2452 g_return_if_fail (E_IS_MAIL_PART_LIST (part_list
));
2453 g_object_ref (part_list
);
2456 if (display
->priv
->part_list
!= NULL
)
2457 g_object_unref (display
->priv
->part_list
);
2459 display
->priv
->part_list
= part_list
;
2461 g_object_notify (G_OBJECT (display
), "part-list");
2465 e_mail_display_get_headers_collapsable (EMailDisplay
*display
)
2467 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), FALSE
);
2469 return display
->priv
->headers_collapsable
;
2473 e_mail_display_set_headers_collapsable (EMailDisplay
*display
,
2474 gboolean collapsable
)
2476 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2478 if (display
->priv
->headers_collapsable
== collapsable
)
2481 display
->priv
->headers_collapsable
= collapsable
;
2482 e_mail_display_reload (display
);
2484 g_object_notify (G_OBJECT (display
), "headers-collapsable");
2488 e_mail_display_get_headers_collapsed (EMailDisplay
*display
)
2490 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), FALSE
);
2492 if (display
->priv
->headers_collapsable
)
2493 return display
->priv
->headers_collapsed
;
2499 e_mail_display_set_headers_collapsed (EMailDisplay
*display
,
2502 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2504 if (display
->priv
->headers_collapsed
== collapsed
)
2507 display
->priv
->headers_collapsed
= collapsed
;
2509 g_object_notify (G_OBJECT (display
), "headers-collapsed");
2513 e_mail_display_load (EMailDisplay
*display
,
2514 const gchar
*msg_uri
)
2516 EMailPartList
*part_list
;
2517 CamelFolder
*folder
;
2518 const gchar
*message_uid
;
2519 const gchar
*default_charset
, *charset
;
2522 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2524 e_mail_display_set_force_load_images (display
, FALSE
);
2526 part_list
= display
->priv
->part_list
;
2527 if (part_list
== NULL
) {
2528 e_web_view_clear (E_WEB_VIEW (display
));
2532 folder
= e_mail_part_list_get_folder (part_list
);
2533 message_uid
= e_mail_part_list_get_message_uid (part_list
);
2534 default_charset
= e_mail_formatter_get_default_charset (display
->priv
->formatter
);
2535 charset
= e_mail_formatter_get_charset (display
->priv
->formatter
);
2537 if (!default_charset
)
2538 default_charset
= "";
2542 uri
= e_mail_part_build_uri (
2543 folder
, message_uid
,
2544 "mode", G_TYPE_INT
, display
->priv
->mode
,
2545 "headers_collapsable", G_TYPE_BOOLEAN
, display
->priv
->headers_collapsable
,
2546 "headers_collapsed", G_TYPE_BOOLEAN
, display
->priv
->headers_collapsed
,
2547 "formatter_default_charset", G_TYPE_STRING
, default_charset
,
2548 "formatter_charset", G_TYPE_STRING
, charset
,
2551 e_web_view_load_uri (E_WEB_VIEW (display
), uri
);
2557 do_reload_display (EMailDisplay
*display
)
2563 gchar
*mode
, *collapsable
, *collapsed
;
2564 const gchar
*default_charset
, *charset
;
2566 web_view
= E_WEB_VIEW (display
);
2567 uri
= (gchar
*) webkit_web_view_get_uri (WEBKIT_WEB_VIEW (web_view
));
2569 display
->priv
->scheduled_reload
= 0;
2571 if (uri
== NULL
|| *uri
== '\0')
2574 if (strstr (uri
, "?") == NULL
) {
2575 e_web_view_reload (web_view
);
2579 soup_uri
= soup_uri_new (uri
);
2581 mode
= g_strdup_printf ("%d", display
->priv
->mode
);
2582 collapsable
= g_strdup_printf ("%d", display
->priv
->headers_collapsable
);
2583 collapsed
= g_strdup_printf ("%d", display
->priv
->headers_collapsed
);
2584 default_charset
= e_mail_formatter_get_default_charset (display
->priv
->formatter
);
2585 charset
= e_mail_formatter_get_charset (display
->priv
->formatter
);
2587 if (!default_charset
)
2588 default_charset
= "";
2592 table
= soup_form_decode (soup_uri
->query
);
2593 g_hash_table_replace (
2594 table
, g_strdup ("mode"), mode
);
2595 g_hash_table_replace (
2596 table
, g_strdup ("headers_collapsable"), collapsable
);
2597 g_hash_table_replace (
2598 table
, g_strdup ("headers_collapsed"), collapsed
);
2599 g_hash_table_replace (
2600 table
, g_strdup ("formatter_default_charset"), (gpointer
) default_charset
);
2601 g_hash_table_replace (
2602 table
, g_strdup ("formatter_charset"), (gpointer
) charset
);
2604 query
= soup_form_encode_hash (table
);
2606 /* The hash table does not free custom values upon destruction */
2608 g_free (collapsable
);
2610 g_hash_table_destroy (table
);
2612 soup_uri_set_query (soup_uri
, query
);
2615 uri
= soup_uri_to_string (soup_uri
, FALSE
);
2616 e_web_view_load_uri (web_view
, uri
);
2618 soup_uri_free (soup_uri
);
2624 e_mail_display_reload (EMailDisplay
*display
)
2626 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2628 if (display
->priv
->scheduled_reload
> 0)
2631 /* Schedule reloading if neccessary.
2632 * Prioritize ahead of GTK+ redraws. */
2633 display
->priv
->scheduled_reload
= g_idle_add_full (
2634 G_PRIORITY_HIGH_IDLE
,
2635 (GSourceFunc
) do_reload_display
, display
, NULL
);
2639 e_mail_display_get_action (EMailDisplay
*display
,
2640 const gchar
*action_name
)
2644 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), NULL
);
2645 g_return_val_if_fail (action_name
!= NULL
, NULL
);
2647 action
= e_web_view_get_action (E_WEB_VIEW (display
), action_name
);
2653 e_mail_display_set_status (EMailDisplay
*display
,
2654 const gchar
*status
)
2658 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2660 str
= g_strdup_printf (
2664 "<meta name=\"generator\" content=\"Evolution Mail\"/>\n"
2665 "<title>Evolution Mail Display</title>\n"
2667 "<body class=\"-e-web-view-background-color e-web-view-text-color\">"
2668 " <style>html, body { height: 100%%; }</style>\n"
2669 " <table border=\"0\" width=\"100%%\" height=\"100%%\">\n"
2670 " <tr height=\"100%%\" valign=\"middle\">\n"
2671 " <td width=\"100%%\" align=\"center\">\n"
2672 " <strong>%s</strong>\n"
2680 e_web_view_load_string (E_WEB_VIEW (display
), str
);
2686 e_mail_display_get_selection_content_multipart_sync (EMailDisplay
*display
,
2688 GCancellable
*cancellable
,
2691 GDBusProxy
*web_extension
;
2693 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), NULL
);
2695 if (!e_web_view_is_selection_active (E_WEB_VIEW (display
)))
2698 web_extension
= e_web_view_get_web_extension_proxy (E_WEB_VIEW (display
));
2699 if (web_extension
) {
2702 result
= e_util_invoke_g_dbus_proxy_call_sync_wrapper_full (
2704 "GetSelectionContentMultipart",
2707 webkit_web_view_get_page_id (
2708 WEBKIT_WEB_VIEW (display
))),
2709 G_DBUS_CALL_FLAGS_NONE
,
2715 gchar
*content
= NULL
;
2716 gboolean text_html
= FALSE
;
2718 g_variant_get (result
, "(sb)", &content
, &text_html
);
2719 g_variant_unref (result
);
2721 *is_html
= text_html
;
2730 e_mail_display_get_selection_plain_text_sync (EMailDisplay
*display
,
2731 GCancellable
*cancellable
,
2734 GDBusProxy
*web_extension
;
2736 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), NULL
);
2738 if (!e_web_view_is_selection_active (E_WEB_VIEW (display
)))
2741 web_extension
= e_web_view_get_web_extension_proxy (E_WEB_VIEW (display
));
2742 if (web_extension
) {
2745 result
= e_util_invoke_g_dbus_proxy_call_sync_wrapper_full (
2747 "GetSelectionContentText",
2750 webkit_web_view_get_page_id (
2751 WEBKIT_WEB_VIEW (display
))),
2752 G_DBUS_CALL_FLAGS_NONE
,
2760 g_variant_get (result
, "(s)", &text
);
2761 g_variant_unref (result
);
2770 e_mail_display_load_images (EMailDisplay
*display
)
2772 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2774 e_mail_display_set_force_load_images (display
, TRUE
);
2775 e_web_view_reload (E_WEB_VIEW (display
));
2779 e_mail_display_set_force_load_images (EMailDisplay
*display
,
2780 gboolean force_load_images
)
2782 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2784 if ((display
->priv
->force_image_load
? 1 : 0) == (force_load_images
? 1 : 0))
2787 display
->priv
->force_image_load
= force_load_images
;
2791 e_mail_display_has_skipped_remote_content_sites (EMailDisplay
*display
)
2795 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), FALSE
);
2797 g_mutex_lock (&display
->priv
->remote_content_lock
);
2799 has_any
= g_hash_table_size (display
->priv
->skipped_remote_content_sites
) > 0;
2801 g_mutex_unlock (&display
->priv
->remote_content_lock
);
2806 /* Free with g_list_free_full (uris, g_free); */
2808 e_mail_display_get_skipped_remote_content_sites (EMailDisplay
*display
)
2812 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), NULL
);
2814 g_mutex_lock (&display
->priv
->remote_content_lock
);
2816 uris
= g_hash_table_get_keys (display
->priv
->skipped_remote_content_sites
);
2818 for (link
= uris
; link
; link
= g_list_next (link
)) {
2819 link
->data
= g_strdup (link
->data
);
2822 g_mutex_unlock (&display
->priv
->remote_content_lock
);
2827 EMailRemoteContent
*
2828 e_mail_display_ref_remote_content (EMailDisplay
*display
)
2830 EMailRemoteContent
*remote_content
;
2832 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), NULL
);
2834 g_mutex_lock (&display
->priv
->remote_content_lock
);
2836 remote_content
= display
->priv
->remote_content
;
2838 g_object_ref (remote_content
);
2840 g_mutex_unlock (&display
->priv
->remote_content_lock
);
2842 return remote_content
;
2846 e_mail_display_set_remote_content (EMailDisplay
*display
,
2847 EMailRemoteContent
*remote_content
)
2849 g_return_if_fail (E_IS_MAIL_DISPLAY (display
));
2851 g_return_if_fail (E_IS_MAIL_REMOTE_CONTENT (remote_content
));
2853 g_mutex_lock (&display
->priv
->remote_content_lock
);
2855 if (display
->priv
->remote_content
== remote_content
) {
2856 g_mutex_unlock (&display
->priv
->remote_content_lock
);
2860 g_clear_object (&display
->priv
->remote_content
);
2861 display
->priv
->remote_content
= remote_content
? g_object_ref (remote_content
) : NULL
;
2863 g_mutex_unlock (&display
->priv
->remote_content_lock
);
2867 e_mail_display_process_magic_spacebar (EMailDisplay
*display
,
2868 gboolean towards_bottom
)
2870 GDBusProxy
*web_extension
;
2872 GError
*local_error
= NULL
;
2873 gboolean processed
= FALSE
;
2875 g_return_val_if_fail (E_IS_MAIL_DISPLAY (display
), FALSE
);
2877 web_extension
= e_web_view_get_web_extension_proxy (E_WEB_VIEW (display
));
2881 result
= e_util_invoke_g_dbus_proxy_call_sync_wrapper_full (
2883 "ProcessMagicSpacebar",
2884 g_variant_new ("(tb)", webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (display
)), towards_bottom
),
2885 G_DBUS_CALL_FLAGS_NONE
,
2891 g_dbus_error_strip_remote_error (local_error
);
2893 e_util_claim_dbus_proxy_call_error (web_extension
, "ProcessMagicSpacebar", local_error
);
2894 g_clear_error (&local_error
);
2897 g_variant_get (result
, "(b)", &processed
);
2898 g_variant_unref (result
);