1 /* Mission Control plugin API - interface to an McdAccountManager for plugins
2  *
3  * Copyright © 2010 Nokia Corporation
4  * Copyright © 2010 Collabora Ltd.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include "config.h"
22 
23 #include <mission-control-plugins/mission-control-plugins.h>
24 #include <mission-control-plugins/implementation.h>
25 #include <mission-control-plugins/debug-internal.h>
26 
27 #define MCP_DEBUG_TYPE MCP_DEBUG_ACCOUNT
28 
29 /**
30  * SECTION:account
31  * @title: McpAccountManager
32  * @short_description: Object representing the account manager, implemented
33  *    by Mission Control
34  * @see_also: #McpAccountStorage
35  * @include: mission-control-plugins/mission-control-plugins.h
36  *
37  * This object represents the Telepathy AccountManager.
38  *
39  * Most virtual methods on the McpAccountStorageIface interface receive an
40  * object provided by Mission Control that implements this interface.
41  * It can be used to manipulate Mission Control's in-memory cache of accounts.
42  *
43  * Only Mission Control should implement this interface.
44  */
45 
46 GType
mcp_account_manager_get_type(void)47 mcp_account_manager_get_type (void)
48 {
49   static gsize once = 0;
50   static GType type = 0;
51 
52   if (g_once_init_enter (&once))
53     {
54       static const GTypeInfo info = {
55           sizeof (McpAccountManagerIface),
56           NULL, /* base_init */
57           NULL, /* base_finalize */
58           NULL, /* class_init */
59           NULL, /* class_finalize */
60           NULL, /* class_data */
61           0, /* instance_size */
62           0, /* n_preallocs */
63           NULL, /* instance_init */
64           NULL /* value_table */
65       };
66 
67       type = g_type_register_static (G_TYPE_INTERFACE,
68           "McpAccountManager", &info, 0);
69       g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
70       g_once_init_leave (&once, 1);
71     }
72 
73   return type;
74 }
75 
76 /**
77  * mcp_account_manager_set_value:
78  * @mcpa: an #McpAccountManager instance
79  * @account: the unique name of an account
80  * @key: the setting whose value we wish to change: either an attribute
81  *  like "DisplayName", or "param-" plus a parameter like "account"
82  * @value: the new value, escaped as if for a #GKeyFile, or %NULL to delete
83  *  the setting/parameter
84  *
85  * Inform Mission Control that @key has changed its value to @value.
86  *
87  * This function may either be called from mcp_account_storage_get(),
88  * or just before emitting #McpAccountStorage::altered-one.
89  *
90  * New plugins should call mcp_account_manager_set_attribute() or
91  * mcp_account_manager_set_parameter() instead.
92  */
93 void
mcp_account_manager_set_value(const McpAccountManager * mcpa,const gchar * account,const gchar * key,const gchar * value)94 mcp_account_manager_set_value (const McpAccountManager *mcpa,
95     const gchar *account,
96     const gchar *key,
97     const gchar *value)
98 {
99   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
100 
101   g_return_if_fail (iface != NULL);
102   g_return_if_fail (iface->set_value != NULL);
103 
104   iface->set_value (mcpa, account, key, value);
105 }
106 
107 /**
108  * mcp_account_manager_set_attribute:
109  * @mcpa: an #McpAccountManager instance
110  * @account: the unique name of an account
111  * @attribute: the name of an attribute, such as "DisplayName"
112  * @value: (allow-none): the new value, or %NULL to delete the attribute
113  * @flags: flags for the new value (only used if @value is non-%NULL)
114  *
115  * Inform Mission Control that @attribute has changed its value to @value.
116  *
117  * If @value is a floating reference, Mission Control will take ownership
118  * of it, much like g_variant_builder_add_value().
119  *
120  * This function may either be called from mcp_account_storage_get(),
121  * or just before emitting #McpAccountStorage::altered-one.
122  */
123 void
mcp_account_manager_set_attribute(const McpAccountManager * mcpa,const gchar * account,const gchar * attribute,GVariant * value,McpAttributeFlags flags)124 mcp_account_manager_set_attribute (const McpAccountManager *mcpa,
125     const gchar *account,
126     const gchar *attribute,
127     GVariant *value,
128     McpAttributeFlags flags)
129 {
130   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
131 
132   g_return_if_fail (iface != NULL);
133   g_return_if_fail (iface->set_attribute != NULL);
134 
135   iface->set_attribute (mcpa, account, attribute, value, flags);
136 }
137 
138 /**
139  * mcp_account_manager_set_parameter:
140  * @mcpa: an #McpAccountManager instance
141  * @account: the unique name of an account
142  * @parameter: the name of a parameter, such as "account", without
143  *  the "param-" prefix
144  * @value: (allow-none): the new value, or %NULL to delete the parameter
145  * @flags: flags for the new value (only used if @value is non-%NULL)
146  *
147  * Inform Mission Control that @parameter has changed its value to @value.
148  *
149  * If @value is a floating reference, Mission Control will take ownership
150  * of it, much like g_variant_builder_add_value().
151  *
152  * This function may either be called from mcp_account_storage_get(),
153  * or just before emitting #McpAccountStorage::altered-one.
154  */
155 void
mcp_account_manager_set_parameter(const McpAccountManager * mcpa,const gchar * account,const gchar * parameter,GVariant * value,McpParameterFlags flags)156 mcp_account_manager_set_parameter (const McpAccountManager *mcpa,
157     const gchar *account,
158     const gchar *parameter,
159     GVariant *value,
160     McpParameterFlags flags)
161 {
162   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
163 
164   g_return_if_fail (iface != NULL);
165   g_return_if_fail (iface->set_parameter != NULL);
166 
167   iface->set_parameter (mcpa, account, parameter, value, flags);
168 }
169 
170 /**
171  * mcp_account_manage_list_keys:
172  * @mcpa: a #McpAccountManager instance
173  * @account: the unique name of an account
174  *
175  * <!-- -->
176  *
177  * Returns: (transfer full): a list of all keys (attributes and
178  *  "param-"-prefixed parameters) stored for @account by any plugin
179  */
180 GStrv
mcp_account_manager_list_keys(const McpAccountManager * mcpa,const gchar * account)181 mcp_account_manager_list_keys (const McpAccountManager *mcpa,
182     const gchar *account)
183 {
184   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
185 
186   g_return_val_if_fail (iface != NULL, NULL);
187   g_return_val_if_fail (iface->list_keys != NULL, NULL);
188   g_return_val_if_fail (account != NULL, NULL);
189 
190   return iface->list_keys (mcpa, account);
191 }
192 
193 /**
194  * mcp_account_manager_get_value:
195  * @mcpa: an #McpAccountManager instance
196  * @account: the unique name of an account
197  * @key: the setting whose value we wish to fetch: either an attribute
198  *  like "DisplayName", or "param-" plus a parameter like "account"
199  *
200  * Fetch a copy of the current value of an account setting held by
201  * the account manager.
202  *
203  * Returns: (transfer full): the value of @key
204  */
205 gchar *
mcp_account_manager_get_value(const McpAccountManager * mcpa,const gchar * account,const gchar * key)206 mcp_account_manager_get_value (const McpAccountManager *mcpa,
207     const gchar *account,
208     const gchar *key)
209 {
210   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
211 
212   g_return_val_if_fail (iface != NULL, NULL);
213   g_return_val_if_fail (iface->set_value != NULL, NULL);
214 
215   return iface->get_value (mcpa, account, key);
216 }
217 
218 /**
219  * mcp_account_manager_parameter_is_secret:
220  * @mcpa: an #McpAccountManager instance
221  * @account: the unique name of an account
222  * @key: the constant string "param-", plus a parameter name like
223  *  "account" or "password"
224  *
225  * Determine whether a given account parameter is secret.
226  * Generally this is determined by MC and passed down to plugins,
227  * but any #McpAccountStorage plugin may decide a parameter is
228  * secret, in which case the return value for this call will
229  * indicate that fact too.
230  *
231  * For historical reasons, this function only operates on parameters,
232  * but requires its argument to be prefixed with "param-".
233  *
234  * Returns: %TRUE for secret settings, %FALSE otherwise
235  */
236 gboolean
mcp_account_manager_parameter_is_secret(const McpAccountManager * mcpa,const gchar * account,const gchar * key)237 mcp_account_manager_parameter_is_secret (const McpAccountManager *mcpa,
238     const gchar *account,
239     const gchar *key)
240 {
241   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
242 
243   g_return_val_if_fail (iface != NULL, FALSE);
244   g_return_val_if_fail (iface->is_secret != NULL, FALSE);
245 
246   return iface->is_secret (mcpa, account, key);
247 }
248 
249 /**
250  * mcp_account_manager_parameter_make_secret:
251  * @mcpa: an #McpAccountManager instance
252  * @account: the unique name of an account
253  * @key: the constant string "param-", plus a parameter name like
254  *  "account" or "password"
255  *
256  * Flag an account setting as secret for the lifetime of this
257  * #McpAccountManager. For instance, this should be called if
258  * @key has been retrieved from gnome-keyring.
259  *
260  * For historical reasons, this function only operates on parameters,
261  * but requires its argument to be prefixed with "param-".
262  */
263 void
mcp_account_manager_parameter_make_secret(const McpAccountManager * mcpa,const gchar * account,const gchar * key)264 mcp_account_manager_parameter_make_secret (const McpAccountManager *mcpa,
265     const gchar *account,
266     const gchar *key)
267 {
268   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
269 
270   g_return_if_fail (iface != NULL);
271   g_return_if_fail (iface->make_secret != NULL);
272 
273   g_debug ("%s.%s should be secret", account, key);
274   iface->make_secret (mcpa, account, key);
275 }
276 
277 /**
278  * mcp_account_manager_get_unique_name:
279  * @mcpa: an #McpAccountManager instance
280  * @manager: the name of the manager
281  * @protocol: the name of the protocol
282  * @params: A gchar * / GValue * hash table of account parameters.
283  *
284  * Generate and return the canonical unique name of this [new] account.
285  * Should not be called for accounts which have already had a name
286  * assigned: Intended for use when a plugin encounters an account which
287  * MC has not previously seen before (ie one created by a 3rd party
288  * in the back-end that the plugin in question provides an interface to).
289  *
290  * Returns: the newly allocated account name, which should be freed
291  * once the caller is done with it.
292  */
293 gchar *
mcp_account_manager_get_unique_name(McpAccountManager * mcpa,const gchar * manager,const gchar * protocol,const GHashTable * params)294 mcp_account_manager_get_unique_name (McpAccountManager *mcpa,
295     const gchar *manager,
296     const gchar *protocol,
297     const GHashTable *params)
298 {
299   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
300 
301   g_return_val_if_fail (iface != NULL, NULL);
302   g_return_val_if_fail (iface->unique_name != NULL, NULL);
303 
304   return iface->unique_name (mcpa, manager, protocol, params);
305 }
306 
307 /**
308  * mcp_account_manager_escape_value_from_keyfile:
309  * @mcpa: a #McpAccountManager
310  * @value: a value with a supported #GType
311  *
312  * Escape @value so it could be passed to g_key_file_set_value().
313  * For instance, escaping the boolean value TRUE returns "true",
314  * and escaping the string value containing one space returns "\s".
315  *
316  * It is a programming error to use an unsupported type.
317  * The supported types are currently %G_TYPE_STRING, %G_TYPE_BOOLEAN,
318  * %G_TYPE_INT, %G_TYPE_UINT, %G_TYPE_INT64, %G_TYPE_UINT64, %G_TYPE_UCHAR,
319  * %G_TYPE_STRV, %DBUS_TYPE_G_OBJECT_PATH and %TP_ARRAY_TYPE_OBJECT_PATH_LIST.
320  *
321  * Returns: the escaped form of @value
322  */
323 gchar *
mcp_account_manager_escape_value_for_keyfile(const McpAccountManager * mcpa,const GValue * value)324 mcp_account_manager_escape_value_for_keyfile (const McpAccountManager *mcpa,
325     const GValue *value)
326 {
327   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
328 
329   g_return_val_if_fail (iface != NULL, NULL);
330   g_return_val_if_fail (iface->escape_value_for_keyfile != NULL, NULL);
331 
332   return iface->escape_value_for_keyfile (mcpa, value);
333 }
334 
335 /**
336  * mcp_account_manager_escape_variant_for_keyfile:
337  * @mcpa: a #McpAccountManager
338  * @variant: a #GVariant with a supported #GVariantType
339  *
340  * Escape @variant so it could be passed to g_key_file_set_value().
341  * For instance, escaping the boolean value TRUE returns "true",
342  * and escaping the string value containing one space returns "\s".
343  *
344  * It is a programming error to use an unsupported type.
345  * The supported types are currently %G_VARIANT_TYPE_STRING,
346  * %G_VARIANT_TYPE_BOOLEAN, %G_VARIANT_TYPE_INT32, %G_VARIANT_TYPE_UINT32,
347  * %G_VARIANT_TYPE_INT64, %G_VARIANT_TYPE_UINT64, %G_VARIANT_TYPE_BYTE,
348  * %G_VARIANT_TYPE_STRING_ARRAY, %G_VARIANT_TYPE_OBJECT_PATH and
349  * %G_VARIANT_TYPE_OBJECT_PATH_ARRAY.
350  *
351  * Returns: (transfer full): the escaped form of @variant
352  */
353 gchar *
mcp_account_manager_escape_variant_for_keyfile(const McpAccountManager * mcpa,GVariant * variant)354 mcp_account_manager_escape_variant_for_keyfile (const McpAccountManager *mcpa,
355     GVariant *variant)
356 {
357   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
358 
359   g_return_val_if_fail (iface != NULL, NULL);
360   g_return_val_if_fail (iface->escape_variant_for_keyfile != NULL, NULL);
361 
362   return iface->escape_variant_for_keyfile (mcpa, variant);
363 }
364 
365 /**
366  * mcp_account_manager_unescape_value_from_keyfile:
367  * @mcpa: a #McpAccountManager
368  * @escaped: an escaped string as returned by g_key_file_get_value()
369  * @value: a value to populate, with a supported #GType
370  * @error: used to raise an error if %FALSE is returned
371  *
372  * Attempt to interpret @escaped as a value of @value's type.
373  * If successful, put it in @value and return %TRUE.
374  *
375  * It is a programming error to try to escape an unsupported type.
376  * The supported types are currently %G_TYPE_STRING, %G_TYPE_BOOLEAN,
377  * %G_TYPE_INT, %G_TYPE_UINT, %G_TYPE_INT64, %G_TYPE_UINT64, %G_TYPE_UCHAR,
378  * %G_TYPE_STRV, %DBUS_TYPE_G_OBJECT_PATH and %TP_ARRAY_TYPE_OBJECT_PATH_LIST.
379  *
380  * Returns: %TRUE if @value was filled in
381  */
382 gboolean
mcp_account_manager_unescape_value_from_keyfile(const McpAccountManager * mcpa,const gchar * escaped,GValue * value,GError ** error)383 mcp_account_manager_unescape_value_from_keyfile (const McpAccountManager *mcpa,
384     const gchar *escaped,
385     GValue *value,
386     GError **error)
387 {
388   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
389 
390   g_return_val_if_fail (iface != NULL, FALSE);
391   g_return_val_if_fail (iface->unescape_value_from_keyfile != NULL, FALSE);
392 
393   return iface->unescape_value_from_keyfile (mcpa, escaped, value, error);
394 }
395 
396 /**
397  * mcp_account_manager_init_value_for_attribute:
398  * @mcpa: a #McpAccountManager
399  * @value: a zero-filled value to initialize
400  * @attribute: a supported Mission Control attribute
401  *
402  * If @attribute is a known Mission Control attribute, initialize @value
403  * with an appropriate type for @attribute and return %TRUE. Otherwise,
404  * return %FALSE.
405  *
406  * Returns: %TRUE if @value was initialized
407  */
408 gboolean
mcp_account_manager_init_value_for_attribute(const McpAccountManager * mcpa,GValue * value,const gchar * attribute)409 mcp_account_manager_init_value_for_attribute (const McpAccountManager *mcpa,
410     GValue *value,
411     const gchar *attribute)
412 {
413   McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
414 
415   g_return_val_if_fail (iface != NULL, FALSE);
416   g_return_val_if_fail (iface->init_value_for_attribute != NULL, FALSE);
417 
418   return iface->init_value_for_attribute (mcpa, value, attribute);
419 }
420