1 /*
2 * e-cal-config-google.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
22 #include <libebackend/libebackend.h>
23
24 #include <e-util/e-util.h>
25
26 #include "e-google-chooser-button.h"
27 #include "module-cal-config-google.h"
28
29 #define GOOGLE_CALENDAR_URI "https://calendar.google.com/calendar/syncselect"
30
31 typedef ESourceConfigBackend ECalConfigGoogle;
32 typedef ESourceConfigBackendClass ECalConfigGoogleClass;
33
34 typedef struct _Context Context;
35
36 struct _Context {
37 GtkWidget *google_button;
38 GtkWidget *user_entry;
39 };
40
41 /* Forward Declarations */
42 GType e_cal_config_google_get_type (void);
43
G_DEFINE_DYNAMIC_TYPE(ECalConfigGoogle,e_cal_config_google,E_TYPE_SOURCE_CONFIG_BACKEND)44 G_DEFINE_DYNAMIC_TYPE (
45 ECalConfigGoogle,
46 e_cal_config_google,
47 E_TYPE_SOURCE_CONFIG_BACKEND)
48
49 static void
50 cal_config_google_context_free (Context *context)
51 {
52 g_object_unref (context->google_button);
53 g_object_unref (context->user_entry);
54
55 g_slice_free (Context, context);
56 }
57
58 static gboolean
cal_config_google_allow_creation(ESourceConfigBackend * backend)59 cal_config_google_allow_creation (ESourceConfigBackend *backend)
60 {
61 ESourceConfig *config;
62 ECalClientSourceType source_type;
63
64 config = e_source_config_backend_get_config (backend);
65
66 source_type = e_cal_source_config_get_source_type (
67 E_CAL_SOURCE_CONFIG (config));
68
69 /* XXX Google's CalDAV interface doesn't support tasks. */
70 return (source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS);
71 }
72
73 static void
cal_config_google_insert_widgets(ESourceConfigBackend * backend,ESource * scratch_source)74 cal_config_google_insert_widgets (ESourceConfigBackend *backend,
75 ESource *scratch_source)
76 {
77 ESourceConfig *config;
78 GtkWidget *widget;
79 Context *context;
80 const gchar *uid;
81 gchar *markup;
82
83 context = g_slice_new0 (Context);
84 uid = e_source_get_uid (scratch_source);
85 config = e_source_config_backend_get_config (backend);
86
87 g_object_set_data_full (
88 G_OBJECT (backend), uid, context,
89 (GDestroyNotify) cal_config_google_context_free);
90
91 context->user_entry = g_object_ref (e_source_config_add_user_entry (config, scratch_source));
92
93 widget = e_google_chooser_button_new (scratch_source, config);
94 e_source_config_insert_widget (config, scratch_source, _("Calendar:"), widget);
95 context->google_button = g_object_ref (widget);
96 gtk_widget_show (widget);
97
98 markup = g_markup_printf_escaped ("<a href=\"%s\">%s</a>", GOOGLE_CALENDAR_URI, _("Enable Calendars to synchronize"));
99
100 widget = gtk_label_new (markup);
101 gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
102 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
103 e_source_config_insert_widget (config, scratch_source, NULL, widget);
104 gtk_widget_show (widget);
105
106 g_free (markup);
107
108 e_source_config_add_refresh_interval (config, scratch_source);
109 }
110
111 static void
cal_config_google_commit_changes(ESourceConfigBackend * backend,ESource * scratch_source)112 cal_config_google_commit_changes (ESourceConfigBackend *backend,
113 ESource *scratch_source)
114 {
115 ESourceBackend *calendar_extension;
116 ESourceWebdav *webdav_extension;
117 ESourceAuthentication *authentication_extension;
118 gboolean can_google_auth;
119 SoupURI *soup_uri;
120
121 /* We need to hard-code a few settings. */
122
123 calendar_extension = e_source_get_extension (
124 scratch_source, E_SOURCE_EXTENSION_CALENDAR);
125
126 webdav_extension = e_source_get_extension (
127 scratch_source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
128
129 authentication_extension = e_source_get_extension (
130 scratch_source, E_SOURCE_EXTENSION_AUTHENTICATION);
131
132 can_google_auth = e_module_cal_config_google_is_supported (backend, NULL) &&
133 g_strcmp0 (e_source_authentication_get_method (authentication_extension), "OAuth2") != 0;
134
135 /* The backend name is actually "caldav" even though the
136 * ESource is a child of the built-in "Google" source. */
137 e_source_backend_set_backend_name (calendar_extension, "caldav");
138
139 soup_uri = e_source_webdav_dup_soup_uri (webdav_extension);
140
141 if (can_google_auth || g_strcmp0 (e_source_authentication_get_method (authentication_extension), "Google") == 0) {
142 /* Prefer 'Google', aka internal OAuth2, authentication method, if available */
143 e_source_authentication_set_method (authentication_extension, "Google");
144
145 /* See https://developers.google.com/google-apps/calendar/caldav/v2/guide */
146 soup_uri_set_host (soup_uri, "apidata.googleusercontent.com");
147 } else {
148 soup_uri_set_host (soup_uri, "www.google.com");
149 }
150
151 if (!soup_uri->path || !*soup_uri->path || g_strcmp0 (soup_uri->path, "/") == 0) {
152 ESourceAuthentication *authentication_extension
153 = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_AUTHENTICATION);
154
155 e_google_chooser_button_construct_default_uri (
156 soup_uri,
157 e_source_authentication_get_user (authentication_extension));
158 }
159
160 /* Google's CalDAV interface requires a secure connection. */
161 soup_uri_set_scheme (soup_uri, SOUP_URI_SCHEME_HTTPS);
162
163 e_source_webdav_set_soup_uri (webdav_extension, soup_uri);
164
165 soup_uri_free (soup_uri);
166 }
167
168 static gboolean
cal_config_google_check_complete(ESourceConfigBackend * backend,ESource * scratch_source)169 cal_config_google_check_complete (ESourceConfigBackend *backend,
170 ESource *scratch_source)
171 {
172 ESourceAuthentication *extension;
173 Context *context;
174 gboolean correct;
175 const gchar *extension_name;
176 const gchar *user;
177
178 context = g_object_get_data (G_OBJECT (backend), e_source_get_uid (scratch_source));
179 g_return_val_if_fail (context != NULL, FALSE);
180
181 extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
182 extension = e_source_get_extension (scratch_source, extension_name);
183 user = e_source_authentication_get_user (extension);
184
185 correct = (user != NULL);
186
187 e_util_set_entry_issue_hint (context->user_entry, correct ? NULL : _("User name cannot be empty"));
188
189 return correct;
190 }
191
192 static void
e_cal_config_google_class_init(ESourceConfigBackendClass * class)193 e_cal_config_google_class_init (ESourceConfigBackendClass *class)
194 {
195 EExtensionClass *extension_class;
196
197 extension_class = E_EXTENSION_CLASS (class);
198 extension_class->extensible_type = E_TYPE_CAL_SOURCE_CONFIG;
199
200 class->parent_uid = "google-stub";
201 class->backend_name = "google";
202 class->allow_creation = cal_config_google_allow_creation;
203 class->insert_widgets = cal_config_google_insert_widgets;
204 class->check_complete = cal_config_google_check_complete;
205 class->commit_changes = cal_config_google_commit_changes;
206 }
207
208 static void
e_cal_config_google_class_finalize(ESourceConfigBackendClass * class)209 e_cal_config_google_class_finalize (ESourceConfigBackendClass *class)
210 {
211 }
212
213 static void
e_cal_config_google_init(ESourceConfigBackend * backend)214 e_cal_config_google_init (ESourceConfigBackend *backend)
215 {
216 }
217
218 void
e_cal_config_google_type_register(GTypeModule * type_module)219 e_cal_config_google_type_register (GTypeModule *type_module)
220 {
221 e_cal_config_google_register_type (type_module);
222 }
223