1 /*
2  * evolution-mailto-handler.c
3  *
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.
7  *
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
11  * for more details.
12  *
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/>.
15  *
16  */
17 
18 #include "evolution-config.h"
19 
20 #include <glib/gi18n-lib.h>
21 #include <libebackend/libebackend.h>
22 
23 #include <shell/e-shell.h>
24 
25 /* Standard GObject macros */
26 #define E_TYPE_MAILTO_HANDLER \
27 	(e_mailto_handler_get_type ())
28 #define E_MAILTO_HANDLER(obj) \
29 	(G_TYPE_CHECK_INSTANCE_CAST \
30 	((obj), E_TYPE_MAILTO_HANDLER, EMailtoHandler))
31 
32 #define MAILTO_COMMAND \
33 	"evolution --component=mail"
34 
35 #define MAILTO_HANDLER "x-scheme-handler/mailto"
36 
37 typedef struct _EMailtoHandler EMailtoHandler;
38 typedef struct _EMailtoHandlerClass EMailtoHandlerClass;
39 
40 struct _EMailtoHandler {
41 	EExtension parent;
42 };
43 
44 struct _EMailtoHandlerClass {
45 	EExtensionClass parent_class;
46 };
47 
48 /* Module Entry Points */
49 void e_module_load (GTypeModule *type_module);
50 void e_module_unload (GTypeModule *type_module);
51 
52 /* Forward Declarations */
53 GType e_mailto_handler_get_type (void);
54 
G_DEFINE_DYNAMIC_TYPE(EMailtoHandler,e_mailto_handler,E_TYPE_EXTENSION)55 G_DEFINE_DYNAMIC_TYPE (EMailtoHandler, e_mailto_handler, E_TYPE_EXTENSION)
56 
57 static EShell *
58 mailto_handler_get_shell (EMailtoHandler *extension)
59 {
60 	EExtensible *extensible;
61 
62 	extensible = e_extension_get_extensible (E_EXTENSION (extension));
63 
64 	return E_SHELL (extensible);
65 }
66 
67 static gboolean
mailto_handler_is_evolution(GAppInfo * app_info)68 mailto_handler_is_evolution (GAppInfo *app_info)
69 {
70 	gint argc;
71 	gchar **argv;
72 	gchar *basename;
73 	gboolean is_evolution;
74 	const gchar *mailto_command;
75 
76 	if (app_info == NULL)
77 		return FALSE;
78 
79 	mailto_command = g_app_info_get_commandline (app_info);
80 	if (mailto_command == NULL)
81 		return FALSE;
82 
83 	/* Tokenize the mailto command. */
84 	if (!g_shell_parse_argv (mailto_command, &argc, &argv, NULL))
85 		return FALSE;
86 
87 	g_return_val_if_fail (argc > 0, FALSE);
88 
89 	/* Check the basename of the first token. */
90 	basename = g_path_get_basename (argv[0]);
91 	is_evolution = g_str_has_prefix (basename, "evolution");
92 	g_free (basename);
93 
94 	g_strfreev (argv);
95 
96 	return is_evolution;
97 }
98 
99 static gboolean
mailto_handler_prompt(EMailtoHandler * extension)100 mailto_handler_prompt (EMailtoHandler *extension)
101 {
102 	GSettings *settings;
103 	GtkWidget *container;
104 	GtkWidget *dialog;
105 	GtkWidget *widget;
106 	const gchar *text;
107 	gchar *markup;
108 	gint response;
109 
110 	dialog = gtk_dialog_new_with_buttons (
111 		"", NULL, 0,
112 		_("Do _not change settings"), GTK_RESPONSE_NO,
113 		_("_Set as default email client"), GTK_RESPONSE_YES,
114 		NULL);
115 
116 	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
117 	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
118 
119 	container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
120 
121 	widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
122 	gtk_container_set_border_width (GTK_CONTAINER (widget), 5);
123 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
124 	gtk_widget_show (widget);
125 
126 	container = widget;
127 
128 	widget = gtk_image_new_from_icon_name ("dialog-question", GTK_ICON_SIZE_DIALOG);
129 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
130 	gtk_widget_show (widget);
131 
132 	widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
133 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
134 	gtk_widget_show (widget);
135 
136 	container = widget;
137 
138 	text = _("Do you want to make Evolution your default email client?");
139 	markup = g_markup_printf_escaped ("<b>%s</b>", text);
140 	widget = gtk_label_new (NULL);
141 	gtk_label_set_markup (GTK_LABEL (widget), markup);
142 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
143 	gtk_widget_show (widget);
144 	g_free (markup);
145 
146 	text = _("_Do not show this message again");
147 	widget = gtk_check_button_new_with_mnemonic (text);
148 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 12);
149 	gtk_widget_show (widget);
150 
151 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
152 
153 	g_settings_bind (
154 		settings, "prompt-check-if-default-mailer",
155 		widget, "active",
156 		G_SETTINGS_BIND_GET |
157 		G_SETTINGS_BIND_SET |
158 		G_SETTINGS_BIND_INVERT_BOOLEAN);
159 
160 	g_object_unref (settings);
161 
162 	/* Direct input focus away from the checkbox. */
163 	widget = gtk_dialog_get_widget_for_response (
164 		GTK_DIALOG (dialog), GTK_RESPONSE_YES);
165 	gtk_widget_grab_focus (widget);
166 
167 	response = gtk_dialog_run (GTK_DIALOG (dialog));
168 
169 	gtk_widget_destroy (dialog);
170 
171 	return (response == GTK_RESPONSE_YES);
172 }
173 
174 static void
mailto_handler_check(EMailtoHandler * extension)175 mailto_handler_check (EMailtoHandler *extension)
176 {
177 	GSettings *settings;
178 	gboolean check_mailto_handler = TRUE;
179 	GAppInfo *app_info = NULL;
180 	GError *error = NULL;
181 
182 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
183 
184 	check_mailto_handler = g_settings_get_boolean (
185 		settings, "prompt-check-if-default-mailer");
186 
187 	g_object_unref (settings);
188 
189 	/* Should we check the "mailto" URI handler? */
190 	if (!check_mailto_handler)
191 		goto exit;
192 
193 	app_info = g_app_info_get_default_for_type (MAILTO_HANDLER, FALSE);
194 
195 	/* Is Evolution already handling "mailto" URIs? */
196 	if (mailto_handler_is_evolution (app_info))
197 		goto exit;
198 
199 	/* Does the user want Evolution to handle them? */
200 	if (!mailto_handler_prompt (extension))
201 		goto exit;
202 
203 	g_clear_object (&app_info);
204 
205 	/* Configure Evolution to be the "mailto" URI handler. */
206 	app_info = g_app_info_create_from_commandline (
207 		MAILTO_COMMAND,
208 		_("Evolution"),
209 		G_APP_INFO_CREATE_SUPPORTS_URIS,
210 		&error);
211 
212 	/* Sanity check. */
213 	g_return_if_fail (
214 		((app_info != NULL) && (error == NULL)) ||
215 		((app_info == NULL) && (error != NULL)));
216 
217 	if (app_info != NULL)
218 		g_app_info_set_as_default_for_type (
219 			app_info, MAILTO_HANDLER, &error);
220 
221 exit:
222 	g_clear_object (&app_info);
223 
224 	if (error != NULL) {
225 		g_warning (
226 			"Failed to register as default handler: %s",
227 			error->message);
228 		g_error_free (error);
229 	}
230 }
231 
232 static void
mailto_handler_constructed(GObject * object)233 mailto_handler_constructed (GObject *object)
234 {
235 	EShell *shell;
236 	EMailtoHandler *extension;
237 
238 	extension = E_MAILTO_HANDLER (object);
239 
240 	shell = mailto_handler_get_shell (extension);
241 
242 	g_signal_connect_swapped (
243 		shell, "event::ready-to-start",
244 		G_CALLBACK (mailto_handler_check), extension);
245 
246 	/* Chain up to parent's constructed() method. */
247 	G_OBJECT_CLASS (e_mailto_handler_parent_class)->constructed (object);
248 }
249 
250 static void
e_mailto_handler_class_init(EMailtoHandlerClass * class)251 e_mailto_handler_class_init (EMailtoHandlerClass *class)
252 {
253 	GObjectClass *object_class;
254 	EExtensionClass *extension_class;
255 
256 	object_class = G_OBJECT_CLASS (class);
257 	object_class->constructed = mailto_handler_constructed;
258 
259 	extension_class = E_EXTENSION_CLASS (class);
260 	extension_class->extensible_type = E_TYPE_SHELL;
261 }
262 
263 static void
e_mailto_handler_class_finalize(EMailtoHandlerClass * class)264 e_mailto_handler_class_finalize (EMailtoHandlerClass *class)
265 {
266 }
267 
268 static void
e_mailto_handler_init(EMailtoHandler * extension)269 e_mailto_handler_init (EMailtoHandler *extension)
270 {
271 }
272 
273 G_MODULE_EXPORT void
e_module_load(GTypeModule * type_module)274 e_module_load (GTypeModule *type_module)
275 {
276 	e_mailto_handler_register_type (type_module);
277 }
278 
279 G_MODULE_EXPORT void
e_module_unload(GTypeModule * type_module)280 e_module_unload (GTypeModule *type_module)
281 {
282 }
283