Git init
[profile/ivi/libsoup2.4.git] / libsoup / soup-password-manager-gnome.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-password-manager-gnome.c: GNOME-keyring-based password manager
4  *
5  * Copyright (C) 2008 Red Hat, Inc.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #define LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY
13
14 #include "soup-password-manager-gnome.h"
15 #include "soup-auth.h"
16 #include "soup-session-feature.h"
17 #include "soup-uri.h"
18
19 #include <gnome-keyring.h>
20
21 static void soup_password_manager_gnome_interface_init (SoupPasswordManagerInterface *password_manager_interface);
22
23 G_DEFINE_TYPE_EXTENDED (SoupPasswordManagerGNOME, soup_password_manager_gnome, G_TYPE_OBJECT, 0,
24                         G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, NULL)
25                         G_IMPLEMENT_INTERFACE (SOUP_TYPE_PASSWORD_MANAGER, soup_password_manager_gnome_interface_init))
26
27 static void get_passwords_async (SoupPasswordManager  *password_manager,
28                                  SoupMessage          *msg,
29                                  SoupAuth             *auth,
30                                  gboolean              retrying,
31                                  GMainContext         *async_context,
32                                  GCancellable         *cancellable,
33                                  SoupPasswordManagerCallback callback,
34                                  gpointer              user_data);
35 static void get_passwords_sync  (SoupPasswordManager  *password_manager,
36                                  SoupMessage          *msg,
37                                  SoupAuth             *auth,
38                                  GCancellable         *cancellable);
39
40 static void
41 soup_password_manager_gnome_init (SoupPasswordManagerGNOME *manager_gnome)
42 {
43 }
44
45 static void
46 soup_password_manager_gnome_class_init (SoupPasswordManagerGNOMEClass *gnome_class)
47 {
48 }
49
50 static void
51 soup_password_manager_gnome_interface_init (SoupPasswordManagerInterface *password_manager_interface)
52 {
53         password_manager_interface->get_passwords_async = get_passwords_async;
54         password_manager_interface->get_passwords_sync = get_passwords_sync;
55 }
56
57
58 static void
59 save_password_callback (GnomeKeyringResult result, guint32 val, gpointer data)
60 {
61 }
62
63 static void
64 async_save_password (SoupAuth *auth, const char *username,
65                      const char *password, gpointer user_data)
66 {
67         SoupURI *uri = user_data;
68
69         gnome_keyring_set_network_password (
70                 NULL, /* use default keyring */
71                 username,
72                 soup_auth_get_realm (auth),
73                 uri->host,
74                 NULL,
75                 uri->scheme,
76                 soup_auth_get_scheme_name (auth),
77                 uri->port,
78                 password,
79                 save_password_callback, NULL, NULL);
80 }
81
82 static void
83 sync_save_password (SoupAuth *auth, const char *username,
84                     const char *password, gpointer user_data)
85 {
86         SoupURI *uri = user_data;
87         guint32 item_id;
88
89         gnome_keyring_set_network_password_sync (
90                 NULL, /* use default keyring */
91                 username,
92                 soup_auth_get_realm (auth),
93                 uri->host,
94                 NULL,
95                 uri->scheme,
96                 soup_auth_get_scheme_name (auth),
97                 uri->port,
98                 password,
99                 &item_id);
100 }
101
102 static void
103 update_auth_for_passwords (SoupAuth *auth, SoupMessage *msg,
104                            GList *passwords, gboolean async)
105 {
106         GnomeKeyringNetworkPasswordData *pdata;
107         SoupURI *uri;
108
109         while (passwords) {
110                 pdata = passwords->data;
111                 soup_auth_has_saved_password (auth, pdata->user,
112                                               pdata->password);
113                 passwords = passwords->next;
114         }
115
116         uri = g_object_get_data (G_OBJECT (auth),
117                                  "SoupPasswordManagerGNOME-save_password-uri");
118         if (uri) {
119                 g_signal_handlers_disconnect_by_func (auth, async_save_password, uri);
120                 g_signal_handlers_disconnect_by_func (auth, sync_save_password, uri);
121         }
122
123         uri = soup_uri_copy (soup_message_get_uri (msg));
124         g_signal_connect (auth, "save_password",
125                           G_CALLBACK (async ? async_save_password : sync_save_password),
126                           uri);
127         g_object_set_data_full (G_OBJECT (auth),
128                                 "SoupPasswordManagerGNOME-save_password-uri",
129                                 uri, (GDestroyNotify)soup_uri_free);
130 }
131
132 typedef struct {
133         SoupPasswordManager *password_manager;
134         SoupMessage *msg;
135         SoupAuth *auth;
136         gboolean retrying;
137
138         SoupPasswordManagerCallback callback;
139         gpointer user_data;
140
141         gpointer request;
142 } SoupPasswordManagerGNOMEAuthData;
143
144 static void
145 find_password_callback (GnomeKeyringResult result, GList *list,
146                         gpointer user_data)
147 {
148         SoupPasswordManagerGNOMEAuthData *auth_data = user_data;
149
150         /* FIXME: check result? */
151
152         update_auth_for_passwords (auth_data->auth, auth_data->msg, list, TRUE);
153         auth_data->callback (auth_data->password_manager,
154                              auth_data->msg, auth_data->auth,
155                              auth_data->retrying, auth_data->user_data);
156
157         /* gnome-keyring will call free_auth_data to clean up for us. */
158 }
159
160 static void
161 free_auth_data (gpointer data)
162 {
163         SoupPasswordManagerGNOMEAuthData *auth_data = data;
164
165         g_object_unref (auth_data->auth);
166         g_object_unref (auth_data->msg);
167         g_slice_free (SoupPasswordManagerGNOMEAuthData, auth_data);
168 }
169
170 static void
171 get_passwords_async (SoupPasswordManager  *password_manager,
172                      SoupMessage          *msg,
173                      SoupAuth             *auth,
174                      gboolean              retrying,
175                      GMainContext         *async_context,
176                      GCancellable         *cancellable,
177                      SoupPasswordManagerCallback callback,
178                      gpointer              user_data)
179 {
180         SoupPasswordManagerGNOMEAuthData *auth_data;
181         SoupURI *uri = soup_message_get_uri (msg);
182
183         auth_data = g_slice_new (SoupPasswordManagerGNOMEAuthData);
184         auth_data->password_manager = password_manager;
185         auth_data->msg = g_object_ref (msg);
186         auth_data->auth = g_object_ref (auth);
187         auth_data->retrying = retrying;
188
189         /* FIXME: async_context, cancellable */
190
191         auth_data->callback = callback;
192         auth_data->user_data = user_data;
193
194         /* FIXME: should we be specifying protocol and port here, or
195          * leaving them NULL/0 and filtering results in the callback?
196          * We don't want to send https passwords to http, but the
197          * reverse might be OK (if that's how other clients tend to
198          * behave).
199          */
200         auth_data->request = gnome_keyring_find_network_password (
201                 NULL,                             /* user -- accept any */
202                 soup_auth_get_realm (auth),       /* domain */
203                 uri->host,                        /* server */
204                 NULL,                             /* object -- unused */
205                 uri->scheme,                      /* protocol */
206                 soup_auth_get_scheme_name (auth), /* authtype */
207                 uri->port,                        /* port */
208                 find_password_callback, auth_data, free_auth_data);
209 }
210
211 static void
212 get_passwords_sync (SoupPasswordManager  *password_manager,
213                     SoupMessage          *msg,
214                     SoupAuth             *auth,
215                     GCancellable         *cancellable)
216 {
217         SoupURI *uri = soup_message_get_uri (msg);
218         GList *results = NULL;
219
220         /* FIXME: cancellable */
221
222         gnome_keyring_find_network_password_sync (
223                 NULL,                             /* user -- accept any */
224                 soup_auth_get_realm (auth),       /* domain */
225                 uri->host,                        /* server */
226                 NULL,                             /* object -- unused */
227                 uri->scheme,                      /* protocol */
228                 soup_auth_get_scheme_name (auth), /* authtype */
229                 uri->port,                        /* port */
230                 &results);
231
232         update_auth_for_passwords (auth, msg, results, FALSE);
233 }