1 /*
2  * account-request.c - object for a currently non-existent account to create
3  *
4  * Copyright © 2012 Collabora Ltd. <http://www.collabora.co.uk/>
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 "telepathy-glib/account-request.h"
24 
25 #include <telepathy-glib/gtypes.h>
26 #include <telepathy-glib/interfaces.h>
27 #include <telepathy-glib/util.h>
28 #include <telepathy-glib/simple-client-factory.h>
29 
30 #define DEBUG_FLAG TP_DEBUG_ACCOUNTS
31 #include "telepathy-glib/dbus-internal.h"
32 #include "telepathy-glib/debug-internal.h"
33 #include "telepathy-glib/util-internal.h"
34 #include "telepathy-glib/variant-util-internal.h"
35 
36 /**
37  * SECTION:account-request
38  * @title: TpAccountRequest
39  * @short_description: object for a currently non-existent account in
40  *   order to create easily without speaking fluent D-Bus
41  * @see_also: #TpAccountManager
42  *
43  * This is a convenience object to aid in the creation of accounts on
44  * a #TpAccountManager without having to construct #GHashTables with
45  * well-known keys. For example:
46  *
47  * |[
48  * static void created_cb (GObject *object, GAsyncResult *res, gpointer user_data);
49  *
50  * static void
51  * create_acount (void)
52  * {
53  *   TpAccountManager *am = tp_account_manager_dup ();
54  *   TpAccountRequest *req;
55  *
56  *   req = tp_account_request_new (am, "gabble", "jabber", "Work Jabber account");
57  *
58  *   tp_account_request_set_parameter (req, "account", "walter.white@lospollos.lit");
59  *
60  *   // ...
61  *
62  *   tp_account_request_create_account_async (req, created_cb, NULL);
63  *   g_object_unref (req);
64  *   g_object_unref (am);
65  * }
66  *
67  * static void
68  * created_cb (GObject *object,
69  *     GAsyncResult *result,
70  *     gpointer user_data)
71  * {
72  *   TpAccountRequest *req = TP_ACCOUNT_REQUEST (object);
73  *   TpAccount *account;
74  *   GError *error = NULL;
75  *
76  *   account = tp_account_request_create_account_finish (req, result, &error);
77  *
78  *   if (account == NULL)
79  *     {
80  *       g_error ("Failed to create account: %s\n", error->message);
81  *       g_clear_error (&error);
82  *       return;
83  *     }
84  *
85  *   // ...
86  *
87  *   g_object_unref (account);
88  * }
89  * ]|
90  *
91  *
92  * Since: 0.19.1
93  */
94 
95 /**
96  * TpAccountRequest:
97  *
98  * An object for representing a currently non-existent account which
99  * is to be created on a #TpAccountManager.
100  *
101  * Since: 0.19.1
102  */
103 
104 /**
105  * TpAccountRequestClass:
106  *
107  * The class of a #TpAccountRequest.
108  */
109 
110 struct _TpAccountRequestPrivate {
111   TpAccountManager *account_manager;
112 
113   GSimpleAsyncResult *result;
114   gboolean created;
115 
116   gchar *cm_name;
117   gchar *proto_name;
118   gchar *display_name;
119 
120   GHashTable *parameters;
121   GHashTable *properties;
122 };
123 
124 G_DEFINE_TYPE (TpAccountRequest, tp_account_request, G_TYPE_OBJECT)
125 
126 /* properties */
127 enum {
128   PROP_ACCOUNT_MANAGER = 1,
129   PROP_CONNECTION_MANAGER,
130   PROP_PROTOCOL,
131   PROP_DISPLAY_NAME,
132   PROP_PARAMETERS,
133   PROP_PROPERTIES,
134   PROP_ICON_NAME,
135   PROP_NICKNAME,
136   PROP_REQUESTED_PRESENCE_TYPE,
137   PROP_REQUESTED_STATUS,
138   PROP_REQUESTED_STATUS_MESSAGE,
139   PROP_AUTOMATIC_PRESENCE_TYPE,
140   PROP_AUTOMATIC_STATUS,
141   PROP_AUTOMATIC_STATUS_MESSAGE,
142   PROP_ENABLED,
143   PROP_CONNECT_AUTOMATICALLY,
144   PROP_SUPERSEDES,
145   PROP_AVATAR,
146   PROP_AVATAR_MIME_TYPE,
147   PROP_SERVICE,
148   PROP_STORAGE_PROVIDER,
149   N_PROPS
150 };
151 
152 static void
tp_account_request_init(TpAccountRequest * self)153 tp_account_request_init (TpAccountRequest *self)
154 {
155   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TYPE_ACCOUNT_REQUEST,
156       TpAccountRequestPrivate);
157 }
158 
159 static void
tp_account_request_constructed(GObject * object)160 tp_account_request_constructed (GObject *object)
161 {
162   TpAccountRequest *self = TP_ACCOUNT_REQUEST (object);
163   TpAccountRequestPrivate *priv = self->priv;
164   void (*chain_up) (GObject *) =
165     ((GObjectClass *) tp_account_request_parent_class)->constructed;
166 
167   if (chain_up != NULL)
168     chain_up (object);
169 
170   g_assert (priv->account_manager != NULL);
171   g_assert (priv->cm_name != NULL);
172   g_assert (priv->proto_name != NULL);
173   g_assert (priv->display_name != NULL);
174 
175   priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
176       g_free, (GDestroyNotify) tp_g_value_slice_free);
177 
178   priv->properties = tp_asv_new (NULL, NULL);
179 }
180 
181 #define GET_PRESENCE_VALUE(key, offset, type) \
182   G_STMT_START { \
183   GValueArray *_arr = tp_asv_get_boxed (self->priv->properties, \
184       key, TP_STRUCT_TYPE_SIMPLE_PRESENCE); \
185   if (_arr != NULL) \
186     g_value_set_##type (value, g_value_get_##type (_arr->values + offset)); \
187   } G_STMT_END
188 
189 static void
tp_account_request_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)190 tp_account_request_get_property (GObject *object,
191     guint prop_id,
192     GValue *value,
193     GParamSpec *pspec)
194 {
195   TpAccountRequest *self = TP_ACCOUNT_REQUEST (object);
196 
197   switch (prop_id)
198     {
199     case PROP_ACCOUNT_MANAGER:
200       g_value_set_object (value, self->priv->account_manager);
201       break;
202     case PROP_CONNECTION_MANAGER:
203       g_value_set_string (value, self->priv->cm_name);
204       break;
205     case PROP_PROTOCOL:
206       g_value_set_string (value, self->priv->proto_name);
207       break;
208     case PROP_DISPLAY_NAME:
209       g_value_set_string (value, self->priv->display_name);
210       break;
211     case PROP_PARAMETERS:
212       g_value_take_variant (value, _tp_asv_to_vardict (self->priv->parameters));
213       break;
214     case PROP_PROPERTIES:
215       g_value_take_variant (value, _tp_asv_to_vardict (self->priv->properties));
216       break;
217     case PROP_ICON_NAME:
218       g_value_set_string (value,
219           tp_asv_get_string (self->priv->properties,
220               TP_PROP_ACCOUNT_ICON));
221       break;
222     case PROP_NICKNAME:
223       g_value_set_string (value,
224           tp_asv_get_string (self->priv->properties,
225               TP_PROP_ACCOUNT_NICKNAME));
226       break;
227     case PROP_REQUESTED_PRESENCE_TYPE:
228       GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_REQUESTED_PRESENCE, 0, uint);
229       break;
230     case PROP_REQUESTED_STATUS:
231       GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_REQUESTED_PRESENCE, 1, string);
232       break;
233     case PROP_REQUESTED_STATUS_MESSAGE:
234       GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_REQUESTED_PRESENCE, 2, string);
235       break;
236     case PROP_AUTOMATIC_PRESENCE_TYPE:
237       GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_AUTOMATIC_PRESENCE, 0, uint);
238       break;
239     case PROP_AUTOMATIC_STATUS:
240       GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_AUTOMATIC_PRESENCE, 1, string);
241       break;
242     case PROP_AUTOMATIC_STATUS_MESSAGE:
243       GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_AUTOMATIC_PRESENCE, 2, string);
244       break;
245     case PROP_ENABLED:
246       g_value_set_boolean (value,
247           tp_asv_get_boolean (self->priv->properties,
248               TP_PROP_ACCOUNT_ENABLED, NULL));
249       break;
250     case PROP_CONNECT_AUTOMATICALLY:
251       g_value_set_boolean (value,
252           tp_asv_get_boolean (self->priv->properties,
253               TP_PROP_ACCOUNT_CONNECT_AUTOMATICALLY,
254               NULL));
255       break;
256     case PROP_SUPERSEDES:
257       {
258         GPtrArray *array = tp_asv_get_boxed (self->priv->properties,
259             TP_PROP_ACCOUNT_SUPERSEDES,
260             TP_ARRAY_TYPE_OBJECT_PATH_LIST);
261 
262         if (array != NULL)
263           {
264             /* add the NULL-termination to make it a real GStrv */
265             g_ptr_array_add (array, NULL);
266             g_value_set_boxed (value, array->pdata);
267             g_ptr_array_remove_index (array, (array->len - 1));
268           }
269         else
270           {
271             g_value_set_boxed (value, NULL);
272           }
273       }
274       break;
275     case PROP_AVATAR:
276       {
277         GValueArray *array = tp_asv_get_boxed (self->priv->properties,
278             TP_PROP_ACCOUNT_INTERFACE_AVATAR_AVATAR,
279             TP_STRUCT_TYPE_AVATAR);
280 
281         if (array != NULL)
282           g_value_set_boxed (value, g_value_get_boxed (array->values));
283       }
284       break;
285     case PROP_AVATAR_MIME_TYPE:
286       {
287         GValueArray *array = tp_asv_get_boxed (self->priv->properties,
288             TP_PROP_ACCOUNT_INTERFACE_AVATAR_AVATAR,
289             TP_STRUCT_TYPE_AVATAR);
290 
291         if (array != NULL)
292           g_value_set_string (value, g_value_get_string (array->values + 1));
293       }
294       break;
295     case PROP_SERVICE:
296       g_value_set_string (value, tp_asv_get_string (self->priv->properties,
297             TP_PROP_ACCOUNT_SERVICE));
298       break;
299     case PROP_STORAGE_PROVIDER:
300       g_value_set_string (value, tp_asv_get_string (self->priv->properties,
301             TP_PROP_ACCOUNT_INTERFACE_STORAGE_STORAGE_PROVIDER));
302       break;
303     default:
304       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
305       break;
306     }
307 }
308 
309 #undef GET_PRESENCE_VALUE
310 
311 static void
tp_account_request_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)312 tp_account_request_set_property (GObject *object,
313     guint property_id,
314     const GValue *value,
315     GParamSpec *pspec)
316 {
317   TpAccountRequest *self = TP_ACCOUNT_REQUEST (object);
318   TpAccountRequestPrivate *priv = self->priv;
319 
320   switch (property_id)
321     {
322     case PROP_ACCOUNT_MANAGER:
323       g_assert (priv->account_manager == NULL);
324       priv->account_manager = g_value_dup_object (value);
325       break;
326     case PROP_CONNECTION_MANAGER:
327       g_assert (priv->cm_name == NULL);
328       priv->cm_name = g_value_dup_string (value);
329       break;
330     case PROP_PROTOCOL:
331       g_assert (priv->proto_name == NULL);
332       priv->proto_name = g_value_dup_string (value);
333       break;
334     case PROP_DISPLAY_NAME:
335       g_assert (priv->display_name == NULL);
336       priv->display_name = g_value_dup_string (value);
337       break;
338     default:
339       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
340       break;
341   }
342 }
343 
344 static void
tp_account_request_dispose(GObject * object)345 tp_account_request_dispose (GObject *object)
346 {
347   TpAccountRequest *self = TP_ACCOUNT_REQUEST (object);
348   TpAccountRequestPrivate *priv = self->priv;
349 
350   g_clear_object (&priv->account_manager);
351 
352   tp_clear_pointer (&priv->parameters, g_hash_table_unref);
353   tp_clear_pointer (&priv->properties, g_hash_table_unref);
354 
355   /* release any references held by the object here */
356 
357   if (G_OBJECT_CLASS (tp_account_request_parent_class)->dispose != NULL)
358     G_OBJECT_CLASS (tp_account_request_parent_class)->dispose (object);
359 }
360 
361 static void
tp_account_request_finalize(GObject * object)362 tp_account_request_finalize (GObject *object)
363 {
364   TpAccountRequest *self = TP_ACCOUNT_REQUEST (object);
365   TpAccountRequestPrivate *priv = self->priv;
366 
367   tp_clear_pointer (&priv->cm_name, g_free);
368   tp_clear_pointer (&priv->proto_name, g_free);
369   tp_clear_pointer (&priv->display_name, g_free);
370 
371   /* free any data held directly by the object here */
372 
373   if (G_OBJECT_CLASS (tp_account_request_parent_class)->finalize != NULL)
374     G_OBJECT_CLASS (tp_account_request_parent_class)->finalize (object);
375 }
376 
377 static void
tp_account_request_class_init(TpAccountRequestClass * klass)378 tp_account_request_class_init (TpAccountRequestClass *klass)
379 {
380   GObjectClass *object_class = (GObjectClass *) klass;
381 
382   g_type_class_add_private (klass, sizeof (TpAccountRequestPrivate));
383 
384   object_class->constructed = tp_account_request_constructed;
385   object_class->get_property = tp_account_request_get_property;
386   object_class->set_property = tp_account_request_set_property;
387   object_class->dispose = tp_account_request_dispose;
388   object_class->finalize = tp_account_request_finalize;
389 
390   /**
391    * TpAccountRequest:account-manager:
392    *
393    * The #TpAccountManager to create the account on.
394    *
395    * Since: 0.19.1
396    */
397   g_object_class_install_property (object_class, PROP_ACCOUNT_MANAGER,
398       g_param_spec_object ("account-manager",
399           "Account manager",
400           "The account's account manager",
401           TP_TYPE_ACCOUNT_MANAGER,
402           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
403 
404   /**
405    * TpAccountRequest:connection-manager:
406    *
407    * The account's connection manager name.
408    *
409    * Since: 0.19.1
410    */
411   g_object_class_install_property (object_class, PROP_CONNECTION_MANAGER,
412       g_param_spec_string ("connection-manager",
413           "Connection manager",
414           "The account's connection manager name",
415           NULL,
416           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
417 
418   /**
419    * TpAccountRequest:protocol:
420    *
421    * The account's machine-readable protocol name, such as "jabber", "msn" or
422    * "local-xmpp". Recommended names for most protocols can be found in the
423    * Telepathy D-Bus Interface Specification.
424    *
425    * Since: 0.19.1
426    */
427   g_object_class_install_property (object_class, PROP_PROTOCOL,
428       g_param_spec_string ("protocol",
429           "Protocol",
430           "The account's protocol name",
431           NULL,
432           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
433 
434   /**
435    * TpAccountRequest:display-name:
436    *
437    * The account's display name. To change this property use
438    * tp_account_request_set_display_name().
439    *
440    * Since: 0.19.1
441    */
442   g_object_class_install_property (object_class, PROP_DISPLAY_NAME,
443       g_param_spec_string ("display-name",
444           "DisplayName",
445           "The account's display name",
446           NULL,
447           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
448 
449   /**
450    * TpAccountRequest:parameters:
451    *
452    * The account's connection parameters. To add a parameter, use
453    * tp_account_request_set_parameter() or another convience function.
454    *
455    * Since: 0.19.1
456    */
457   g_object_class_install_property (object_class, PROP_PARAMETERS,
458       g_param_spec_variant ("parameters",
459           "Parameters",
460           "Connection parameters of the account",
461           G_VARIANT_TYPE_VARDICT, NULL,
462           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
463 
464   /**
465    * TpAccountRequest:properties:
466    *
467    * The account's properties.
468    *
469    * Since: 0.19.1
470    */
471   g_object_class_install_property (object_class, PROP_PROPERTIES,
472       g_param_spec_variant ("properties",
473           "Properties",
474           "Account properties",
475           G_VARIANT_TYPE_VARDICT, NULL,
476           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
477 
478   /**
479    * TpAccountRequest:icon-name:
480    *
481    * The account's icon name. To change this propery, use
482    * tp_account_request_set_icon_name().
483    *
484    * Since: 0.19.1
485    */
486   g_object_class_install_property (object_class, PROP_ICON_NAME,
487       g_param_spec_string ("icon-name",
488           "Icon",
489           "The account's icon name",
490           NULL,
491           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
492 
493   /**
494    * TpAccountRequest:nickname:
495    *
496    * The account's nickname. To change this property use
497    * tp_account_request_set_nickname().
498    *
499    * Since: 0.19.1
500    */
501   g_object_class_install_property (object_class, PROP_NICKNAME,
502       g_param_spec_string ("nickname",
503           "Nickname",
504           "The account's nickname",
505           NULL,
506           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
507 
508   /**
509    * TpAccountRequest:requested-presence-type:
510    *
511    * The account's requested presence type (a
512    * #TpConnectionPresenceType). To change this property use
513    * tp_account_request_set_requested_presence().
514    *
515    * Since: 0.19.1
516    */
517   g_object_class_install_property (object_class, PROP_REQUESTED_PRESENCE_TYPE,
518       g_param_spec_uint ("requested-presence-type",
519           "RequestedPresence",
520           "The account's requested presence type",
521           0,
522           TP_NUM_CONNECTION_PRESENCE_TYPES,
523           TP_CONNECTION_PRESENCE_TYPE_UNSET,
524           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
525 
526   /**
527    * TpAccountRequest:requested-status:
528    *
529    * The requested Status string of the account. To change this
530    * property use tp_account_request_set_requested_presence().
531    *
532    * Since: 0.19.1
533    */
534   g_object_class_install_property (object_class, PROP_REQUESTED_STATUS,
535       g_param_spec_string ("requested-status",
536           "RequestedStatus",
537           "The account's requested status string",
538           NULL,
539           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
540 
541   /**
542    * TpAccountRequest:requested-status-message:
543    *
544    * The requested status message message of the account. To change
545    * this property use tp_account_request_set_requested_presence().
546    *
547    * Since: 0.19.1
548    */
549   g_object_class_install_property (object_class, PROP_REQUESTED_STATUS_MESSAGE,
550       g_param_spec_string ("requested-status-message",
551           "RequestedStatusMessage",
552           "The requested Status message string of the account",
553           NULL,
554           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
555 
556   /**
557    * TpAccountRequest:automatic-presence-type:
558    *
559    * The account's automatic presence type (a
560    * #TpConnectionPresenceType). To change this property use
561    * tp_account_request_set_automatic_presence().
562    *
563    * When the account is put online automatically, for instance to
564    * make a channel request or because network connectivity becomes
565    * available, the automatic presence type, status and message will
566    * be copied to their "requested" counterparts.
567    *
568    * Since: 0.19.1
569    */
570   g_object_class_install_property (object_class, PROP_AUTOMATIC_PRESENCE_TYPE,
571       g_param_spec_uint ("automatic-presence-type",
572           "AutomaticPresence type",
573           "Presence type used to put the account online automatically",
574           0,
575           TP_NUM_CONNECTION_PRESENCE_TYPES,
576           TP_CONNECTION_PRESENCE_TYPE_UNSET,
577           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
578 
579   /**
580    * TpAccountRequest:automatic-status:
581    *
582    * The string status name to use in conjunction with the
583    * #TpAccountRequest:automatic-presence-type. To change this property
584    * use tp_account_request_set_automatic_presence().
585    *
586    * Since: 0.19.1
587    */
588   g_object_class_install_property (object_class, PROP_AUTOMATIC_STATUS,
589       g_param_spec_string ("automatic-status",
590           "AutomaticPresence status",
591           "Presence status used to put the account online automatically",
592           NULL,
593           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
594 
595   /**
596    * TpAccountRequest:automatic-status-message:
597    *
598    * The user-defined message to use in conjunction with the
599    * #TpAccount:automatic-presence-type. To change this property use
600    * tp_account_request_set_automatic_presence().
601    *
602    * Since: 0.19.1
603    */
604   g_object_class_install_property (object_class, PROP_AUTOMATIC_STATUS_MESSAGE,
605       g_param_spec_string ("automatic-status-message",
606           "AutomaticPresence message",
607           "User-defined message used to put the account online automatically",
608           NULL,
609           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
610 
611   /**
612    * TpAccountRequest:enabled:
613    *
614    * Whether the account is enabled or not. To change this property
615    * use tp_account_request_set_enabled().
616    *
617    * Since: 0.19.1
618    */
619   g_object_class_install_property (object_class, PROP_ENABLED,
620       g_param_spec_boolean ("enabled",
621           "Enabled",
622           "Whether this account is enabled or not",
623           FALSE,
624           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
625 
626   /**
627    * TpAccountRequest:connect-automatically:
628    *
629    * Whether the account should connect automatically or not. To change this
630    * property, use tp_account_request_set_connect_automatically().
631    *
632    * Since: 0.19.1
633    */
634   g_object_class_install_property (object_class, PROP_CONNECT_AUTOMATICALLY,
635       g_param_spec_boolean ("connect-automatically",
636           "ConnectAutomatically",
637           "Whether this account should connect automatically or not",
638           FALSE,
639           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
640 
641   /**
642    * TpAccountRequest:supersedes:
643    *
644    * The object paths of previously-active accounts superseded by this one.
645    * For instance, this can be used in a logger to read old logs for an
646    * account that has been migrated from one connection manager to another.
647    *
648    * To add to this property use tp_account_request_add_supersedes().
649    *
650    * Since: 0.19.1
651    */
652   g_object_class_install_property (object_class, PROP_SUPERSEDES,
653       g_param_spec_boxed ("supersedes",
654         "Supersedes",
655         "Accounts superseded by this one",
656         G_TYPE_STRV,
657         G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
658 
659   /**
660    * TpAccountRequest:avatar:
661    *
662    * The avatar set on the account. The avatar's mime type can be read
663    * in the #TpAccountRequest:avatar-mime-type property. To change this
664    * property, use tp_account_request_set_avatar().
665    *
666    * Since: 0.19.1
667    */
668   g_object_class_install_property (object_class, PROP_AVATAR,
669       g_param_spec_boxed ("avatar",
670         "Avatar",
671         "The account's avatar data",
672         G_TYPE_ARRAY,
673         G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
674 
675   /**
676    * TpAccountRequest:avatar-mime-type:
677    *
678    * The mime type of the #TpAccountRequest:avatar property. To change
679    * this property, use tp_account_request_set_avatar().
680    *
681    * Since: 0.19.1
682    */
683   g_object_class_install_property (object_class, PROP_AVATAR_MIME_TYPE,
684       g_param_spec_string ("avatar-mime-type",
685           "Avatar mime type",
686           "The account's avatar's mime type",
687           NULL,
688           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
689 
690   /**
691    * TpAccountRequest:service:
692    *
693    * A string describing the service of the account, which must
694    * consist only of ASCII letters, numbers and hyphen/minus signs,
695    * and start with a letter (matching the requirements for
696    * Protocol). To change this property, use
697    * tp_account_request_set_service().
698    *
699    * Since: 0.19.1
700    */
701   g_object_class_install_property (object_class, PROP_SERVICE,
702       g_param_spec_string ("service",
703           "Service",
704           "The account's service",
705           NULL,
706           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
707 
708   /**
709    * TpAccountRequest:storage-provider:
710    *
711    * The account's storage provider. To change this property use
712    * tp_account_request_set_storage_provider().
713    *
714    * Since: 0.19.4
715    */
716   g_object_class_install_property (object_class, PROP_STORAGE_PROVIDER,
717       g_param_spec_string ("storage-provider",
718           "Storage Provider",
719           "The account's storage provider",
720           NULL,
721           G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
722 }
723 
724 /**
725  * tp_account_request_new:
726  * @account_manager: the #TpAccountManager to create the account on
727  * @manager: the name of the connection manager
728  * @protocol: the name of the protocol on @manager
729  * @display_name: the user-visible name of this account
730  *
731  * Convenience function to create a new account request object which
732  * will assist in the creation of a new account on @account_manager,
733  * using connection manager @manager, and protocol @protocol.
734  *
735  * Returns: (transfer full): a new reference to an account request
736  *   object, or %NULL if any argument is incorrect
737  *
738  * Since: 0.19.1
739  */
740 TpAccountRequest *
tp_account_request_new(TpAccountManager * account_manager,const gchar * manager,const gchar * protocol,const gchar * display_name)741 tp_account_request_new (TpAccountManager *account_manager,
742     const gchar *manager,
743     const gchar *protocol,
744     const gchar *display_name)
745 {
746   g_return_val_if_fail (TP_IS_ACCOUNT_MANAGER (account_manager), NULL);
747   g_return_val_if_fail (manager != NULL, NULL);
748   g_return_val_if_fail (protocol != NULL, NULL);
749 
750   return g_object_new (TP_TYPE_ACCOUNT_REQUEST,
751       "account-manager", account_manager,
752       "connection-manager", manager,
753       "protocol", protocol,
754       "display-name", display_name,
755       NULL);
756 }
757 
758 /**
759  * tp_account_request_new_from_protocol:
760  * @account_manager: the #TpAccountManager to create the account on
761  * @protocol: a #TpProtocol
762  * @display_name: the user-visible name of this account
763  *
764  * Convenience function to create a new #TpAccountRequest object using
765  * a #TpProtocol instance, instead of specifying connection manager
766  * and protocol name specifically. See tp_account_request_new() for
767  * more details.
768  *
769  * Returns: (transfer full): a new reference to an account request
770  *   object, or %NULL if any argument is incorrect
771  *
772  * Since: 0.19.1
773  */
774 TpAccountRequest *
tp_account_request_new_from_protocol(TpAccountManager * account_manager,TpProtocol * protocol,const gchar * display_name)775 tp_account_request_new_from_protocol (TpAccountManager *account_manager,
776     TpProtocol *protocol,
777     const gchar *display_name)
778 {
779   g_return_val_if_fail (TP_IS_ACCOUNT_MANAGER (account_manager), NULL);
780   g_return_val_if_fail (TP_IS_PROTOCOL (protocol), NULL);
781 
782   return g_object_new (TP_TYPE_ACCOUNT_REQUEST,
783       "account-manager", account_manager,
784       "connection-manager", tp_protocol_get_cm_name (protocol),
785       "protocol", tp_protocol_get_name (protocol),
786       "display-name", display_name,
787       NULL);
788 }
789 
790 /**
791  * tp_account_request_set_display_name:
792  * @self: a #TpAccountRequest
793  * @name: a display name for the account
794  *
795  * Set the display name for the new account, @self, to @name. Use the
796  * #TpAccountRequest:display-name property to read the current display
797  * name.
798  *
799  * Since: 0.19.1
800  */
801 void
tp_account_request_set_display_name(TpAccountRequest * self,const gchar * name)802 tp_account_request_set_display_name (TpAccountRequest *self,
803     const gchar *name)
804 {
805   TpAccountRequestPrivate *priv;
806 
807   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
808   g_return_if_fail (name != NULL);
809 
810   priv = self->priv;
811 
812   g_return_if_fail (priv->result == NULL && !priv->created);
813 
814   g_free (priv->display_name);
815   priv->display_name = g_strdup (name);
816 }
817 
818 /**
819  * tp_account_request_set_icon_name:
820  * @self: a #TpAccountRequest
821  * @icon: an icon name for the account
822  *
823  * Set the icon name for the new account, @self, to @icon. Use the
824  * #TpAccountRequest:icon-name property to read the current icon name.
825  *
826  * Since: 0.19.1
827  */
828 void
tp_account_request_set_icon_name(TpAccountRequest * self,const gchar * icon)829 tp_account_request_set_icon_name (TpAccountRequest *self,
830     const gchar *icon)
831 {
832   TpAccountRequestPrivate *priv;
833 
834   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
835   g_return_if_fail (icon != NULL);
836 
837   priv = self->priv;
838 
839   g_return_if_fail (priv->result == NULL && !priv->created);
840 
841   tp_asv_set_string (priv->properties, TP_PROP_ACCOUNT_ICON, icon);
842 }
843 
844 /**
845  * tp_account_request_set_nickname:
846  * @self: a #TpAccountRequest
847  * @nickname: a nickname for the account
848  *
849  * Set the nickname for the new account, @self, to @nickname. Use the
850  * #TpAccountRequest:nickname property to read the current nickname.
851  *
852  * Since: 0.19.1
853  */
854 void
tp_account_request_set_nickname(TpAccountRequest * self,const gchar * nickname)855 tp_account_request_set_nickname (TpAccountRequest *self,
856     const gchar *nickname)
857 {
858   TpAccountRequestPrivate *priv;
859 
860   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
861   g_return_if_fail (nickname != NULL);
862 
863   priv = self->priv;
864 
865   g_return_if_fail (priv->result == NULL && !priv->created);
866 
867   tp_asv_set_string (priv->properties, TP_PROP_ACCOUNT_NICKNAME, nickname);
868 }
869 
870 /**
871  * tp_account_request_set_requested_presence:
872  * @self: a #TpAccountRequest
873  * @presence: the requested presence type
874  * @status: the requested presence status
875  * @message: the requested presence message
876  *
877  * Set the requested presence for the new account, @self, to the type
878  * (@presence, @status), with message @message. Use the
879  * #TpAccountRequest:requested-presence-type,
880  * #TpAccountRequest:requested-status, and
881  * #TpAccountRequest:requested-status-message properties to read the
882  * current requested presence.
883  *
884  * Since: 0.19.1
885  */
886 void
tp_account_request_set_requested_presence(TpAccountRequest * self,TpConnectionPresenceType presence,const gchar * status,const gchar * message)887 tp_account_request_set_requested_presence (TpAccountRequest *self,
888     TpConnectionPresenceType presence,
889     const gchar *status,
890     const gchar *message)
891 {
892   TpAccountRequestPrivate *priv;
893   GValue *value;
894   GValueArray *arr;
895 
896   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
897 
898   priv = self->priv;
899 
900   g_return_if_fail (priv->result == NULL && !priv->created);
901 
902   value = tp_g_value_slice_new_take_boxed (TP_STRUCT_TYPE_SIMPLE_PRESENCE,
903       dbus_g_type_specialized_construct (TP_STRUCT_TYPE_SIMPLE_PRESENCE));
904   arr = (GValueArray *) g_value_get_boxed (value);
905 
906   g_value_set_uint (arr->values, presence);
907   g_value_set_string (arr->values + 1, status);
908   g_value_set_string (arr->values + 2, message);
909 
910   g_hash_table_insert (priv->properties,
911       TP_PROP_ACCOUNT_REQUESTED_PRESENCE, value);
912 }
913 
914 /**
915  * tp_account_request_set_automatic_presence:
916  * @self: a #TpAccountRequest
917  * @presence: the automatic presence type
918  * @status: the automatic presence status
919  * @message: the automatic presence message
920  *
921  * Set the automatic presence for the new account, @self, to the type
922  * (@presence, @status), with message @message. Use the
923  * #TpAccountRequest:automatic-presence-type,
924  * #TpAccountRequest:automatic-status, and
925  * #TpAccountRequest:automatic-status-message properties to read the
926  * current automatic presence.
927  *
928  * Since: 0.19.1
929  */
930 void
tp_account_request_set_automatic_presence(TpAccountRequest * self,TpConnectionPresenceType presence,const gchar * status,const gchar * message)931 tp_account_request_set_automatic_presence (TpAccountRequest *self,
932     TpConnectionPresenceType presence,
933     const gchar *status,
934     const gchar *message)
935 {
936   TpAccountRequestPrivate *priv;
937   GValue *value;
938   GValueArray *arr;
939 
940   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
941 
942   priv = self->priv;
943 
944   g_return_if_fail (priv->result == NULL && !priv->created);
945 
946   value = tp_g_value_slice_new_take_boxed (TP_STRUCT_TYPE_SIMPLE_PRESENCE,
947       dbus_g_type_specialized_construct (TP_STRUCT_TYPE_SIMPLE_PRESENCE));
948   arr = (GValueArray *) g_value_get_boxed (value);
949 
950   g_value_set_uint (arr->values, presence);
951   g_value_set_string (arr->values + 1, status);
952   g_value_set_string (arr->values + 2, message);
953 
954   g_hash_table_insert (priv->properties,
955       TP_PROP_ACCOUNT_AUTOMATIC_PRESENCE, value);
956 }
957 
958 /**
959  * tp_account_request_set_enabled:
960  * @self: a #TpAccountRequest
961  * @enabled: %TRUE if the account is to be enabled
962  *
963  * Set the enabled property of the account on creation to
964  * @enabled. Use the #TpAccountRequest:enabled property to read the
965  * current enabled value.
966  *
967  * Since: 0.19.1
968  */
969 void
tp_account_request_set_enabled(TpAccountRequest * self,gboolean enabled)970 tp_account_request_set_enabled (TpAccountRequest *self,
971     gboolean enabled)
972 {
973   TpAccountRequestPrivate *priv;
974 
975   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
976 
977   priv = self->priv;
978 
979   g_return_if_fail (priv->result == NULL && !priv->created);
980 
981   tp_asv_set_boolean (priv->properties, TP_PROP_ACCOUNT_ENABLED, enabled);
982 }
983 
984 /**
985  * tp_account_request_set_connect_automatically:
986  * @self: a #TpAccountRequest
987  * @connect_automatically: %TRUE if the account is to connect automatically
988  *
989  * Set the connect automatically property of the account on creation
990  * to @connect_automatically so that the account is brought online to
991  * the automatic presence. Use the
992  * #TpAccountRequest:connect-automatically property to read the current
993  * connect automatically value.
994  *
995  * Since: 0.19.1
996  */
997 void
tp_account_request_set_connect_automatically(TpAccountRequest * self,gboolean connect_automatically)998 tp_account_request_set_connect_automatically (TpAccountRequest *self,
999     gboolean connect_automatically)
1000 {
1001   TpAccountRequestPrivate *priv;
1002 
1003   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
1004 
1005   priv = self->priv;
1006 
1007   g_return_if_fail (priv->result == NULL && !priv->created);
1008 
1009   tp_asv_set_boolean (priv->properties,
1010       TP_PROP_ACCOUNT_CONNECT_AUTOMATICALLY,
1011       connect_automatically);
1012 }
1013 
1014 /**
1015  * tp_account_request_add_supersedes:
1016  * @self: a #TpAccountRequest
1017  * @superseded_path: an account object path to add to the supersedes
1018  *   list
1019  *
1020  * Add an account object path to the list of superseded accounts which
1021  * this new account will supersede. Use the
1022  * #TpAccountRequest:supersedes property to read the current list of
1023  * superseded accounts.
1024  *
1025  * Since: 0.19.1
1026  */
1027 void
tp_account_request_add_supersedes(TpAccountRequest * self,const gchar * superseded_path)1028 tp_account_request_add_supersedes (TpAccountRequest *self,
1029     const gchar *superseded_path)
1030 {
1031   TpAccountRequestPrivate *priv;
1032   GPtrArray *array;
1033 
1034   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
1035   g_return_if_fail (g_variant_is_object_path (superseded_path));
1036 
1037   priv = self->priv;
1038 
1039   g_return_if_fail (priv->result == NULL && !priv->created);
1040 
1041   array = tp_asv_get_boxed (priv->properties,
1042       TP_PROP_ACCOUNT_SUPERSEDES,
1043       TP_ARRAY_TYPE_OBJECT_PATH_LIST);
1044 
1045   if (array == NULL)
1046     {
1047       array = g_ptr_array_new ();
1048 
1049       tp_asv_take_boxed (priv->properties,
1050           TP_PROP_ACCOUNT_SUPERSEDES,
1051           TP_ARRAY_TYPE_OBJECT_PATH_LIST, array);
1052     }
1053 
1054   g_ptr_array_add (array, g_strdup (superseded_path));
1055 }
1056 
1057 /**
1058  * tp_account_request_set_avatar:
1059  * @self: a #TpAccountRequest
1060  * @avatar: (allow-none) (array length=len): a new avatar to set; can
1061  *   be %NULL only if %len equals 0
1062  * @len: the length of the new avatar
1063  * @mime_type: (allow-none): the MIME type of the new avatar; can be %NULL
1064  *  only if @len equals 0
1065  *
1066  * Set the avatar of the account @self to @avatar. Use the
1067  * #TpAccountRequest:avatar and #TpAccountRequest:avatar-mime-type
1068  * properties to read the current avatar.
1069  *
1070  * Since: 0.19.1
1071  */
1072 void
tp_account_request_set_avatar(TpAccountRequest * self,const guchar * avatar,gsize len,const gchar * mime_type)1073 tp_account_request_set_avatar (TpAccountRequest *self,
1074     const guchar *avatar,
1075     gsize len,
1076     const gchar *mime_type)
1077 {
1078   TpAccountRequestPrivate *priv;
1079   GArray *tmp;
1080   GValueArray *arr;
1081 
1082   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
1083   g_return_if_fail (avatar != NULL || len == 0);
1084   g_return_if_fail (mime_type != NULL || len == 0);
1085 
1086   priv = self->priv;
1087 
1088   g_return_if_fail (priv->result == NULL && !priv->created);
1089 
1090   tmp = g_array_new (FALSE, FALSE, sizeof (guchar));
1091 
1092   if (len > 0)
1093     g_array_append_vals (tmp, avatar, len);
1094 
1095   arr = tp_value_array_build (2,
1096       TP_TYPE_UCHAR_ARRAY, tmp,
1097       G_TYPE_STRING, mime_type,
1098       G_TYPE_INVALID);
1099 
1100   g_array_unref (tmp);
1101 
1102   tp_asv_take_boxed (priv->properties,
1103       TP_PROP_ACCOUNT_INTERFACE_AVATAR_AVATAR,
1104       TP_STRUCT_TYPE_AVATAR, arr);
1105 }
1106 
1107 /**
1108  * tp_account_request_set_service:
1109  * @self: a #TpAccountRequest
1110  * @service: the service name for
1111  *
1112  * Set the service property of the account to @service. Use the
1113  * #TpAccountRequest:service property to read the current value.
1114  *
1115  * Since: 0.19.1
1116  */
1117 void
tp_account_request_set_service(TpAccountRequest * self,const gchar * service)1118 tp_account_request_set_service (TpAccountRequest *self,
1119     const gchar *service)
1120 {
1121   TpAccountRequestPrivate *priv;
1122 
1123   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
1124   g_return_if_fail (service != NULL);
1125 
1126   priv = self->priv;
1127 
1128   g_return_if_fail (priv->result == NULL && !priv->created);
1129 
1130   tp_asv_set_string (priv->properties,
1131       TP_PROP_ACCOUNT_SERVICE, service);
1132 }
1133 
1134 /**
1135  * tp_account_request_set_storage_provider:
1136  * @self: a #TpAccountRequest
1137  * @provider: the name of an account storage implementation
1138  *
1139  * Set the account storage to use when creating the account. Use the
1140  * #TpAccountRequest:storage-provider property to read the current value.
1141  *
1142  * Since: 0.19.4
1143  */
1144 void
tp_account_request_set_storage_provider(TpAccountRequest * self,const gchar * provider)1145 tp_account_request_set_storage_provider (TpAccountRequest *self,
1146     const gchar *provider)
1147 {
1148   TpAccountRequestPrivate *priv;
1149 
1150   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
1151 
1152   priv = self->priv;
1153 
1154   g_return_if_fail (priv->result == NULL && !priv->created);
1155 
1156   tp_asv_set_string (priv->properties,
1157       TP_PROP_ACCOUNT_INTERFACE_STORAGE_STORAGE_PROVIDER, provider);
1158 }
1159 
1160 /**
1161  * tp_account_request_set_parameter:
1162  * @self: a #TpAccountRequest
1163  * @key: the parameter key
1164  * @value: (transfer none): a variant containing the parameter value
1165  *
1166  * Set an account parameter, @key, to @value. Use the
1167  * #TpAccountRequest:parameters property to read the current list of
1168  * set parameters.
1169  *
1170  * Parameters can be unset using tp_account_request_unset_parameter().
1171  *
1172  * Since: 0.19.1
1173  */
1174 void
tp_account_request_set_parameter(TpAccountRequest * self,const gchar * key,GVariant * value)1175 tp_account_request_set_parameter (TpAccountRequest *self,
1176     const gchar *key,
1177     GVariant *value)
1178 {
1179   TpAccountRequestPrivate *priv;
1180   GValue one = G_VALUE_INIT, *two;
1181 
1182   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
1183   g_return_if_fail (key != NULL);
1184   g_return_if_fail (value != NULL);
1185 
1186   priv = self->priv;
1187 
1188   g_return_if_fail (priv->result == NULL && !priv->created);
1189 
1190   dbus_g_value_parse_g_variant (value, &one);
1191   two = tp_g_value_slice_dup (&one);
1192 
1193   g_hash_table_insert (priv->parameters, g_strdup (key), two);
1194 
1195   g_value_unset (&one);
1196 }
1197 
1198 /**
1199  * tp_account_request_unset_parameter:
1200  * @self: a #TpAccountRequest
1201  * @key: the parameter key
1202  *
1203  * Unset the account parameter @key which has previously been set
1204  * using tp_account_request_set_parameter() or another convenience
1205  * function.
1206  *
1207  * Since: 0.19.1
1208  */
1209 void
tp_account_request_unset_parameter(TpAccountRequest * self,const gchar * key)1210 tp_account_request_unset_parameter (TpAccountRequest *self,
1211     const gchar *key)
1212 {
1213   TpAccountRequestPrivate *priv;
1214 
1215   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
1216   g_return_if_fail (key != NULL);
1217 
1218   priv = self->priv;
1219 
1220   g_return_if_fail (priv->result == NULL && !priv->created);
1221 
1222   g_hash_table_remove (priv->parameters, key);
1223 }
1224 
1225 /**
1226  * tp_account_request_set_parameter_string: (skip)
1227  * @self: a #TpAccountRequest
1228  * @key: the parameter key
1229  * @value: the parameter value
1230  *
1231  * Convenience function to set an account parameter string value. See
1232  * tp_account_request_set_parameter() for more details.
1233  *
1234  * Since: 0.19.1
1235  */
1236 void
tp_account_request_set_parameter_string(TpAccountRequest * self,const gchar * key,const gchar * value)1237 tp_account_request_set_parameter_string (TpAccountRequest *self,
1238     const gchar *key,
1239     const gchar *value)
1240 {
1241   TpAccountRequestPrivate *priv;
1242 
1243   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
1244   g_return_if_fail (key != NULL);
1245   g_return_if_fail (value != NULL);
1246 
1247   priv = self->priv;
1248 
1249   g_return_if_fail (priv->result == NULL && !priv->created);
1250 
1251   g_hash_table_insert (priv->parameters, g_strdup (key),
1252       tp_g_value_slice_new_string (value));
1253 }
1254 
1255 static void
tp_account_request_account_prepared_cb(GObject * object,GAsyncResult * result,gpointer user_data)1256 tp_account_request_account_prepared_cb (GObject *object,
1257     GAsyncResult *result,
1258     gpointer user_data)
1259 {
1260   TpAccountRequest *self = user_data;
1261   TpAccountRequestPrivate *priv = self->priv;
1262   GError *error = NULL;
1263 
1264   if (!tp_proxy_prepare_finish (object, result, &error))
1265     {
1266       DEBUG ("Error preparing account: %s", error->message);
1267       g_simple_async_result_take_error (priv->result, error);
1268     }
1269 
1270   g_simple_async_result_complete (priv->result);
1271   g_clear_object (&priv->result);
1272 }
1273 
1274 static void
tp_account_request_create_account_cb(TpAccountManager * proxy,const gchar * account_path,const GError * error,gpointer user_data,GObject * weak_object)1275 tp_account_request_create_account_cb (TpAccountManager *proxy,
1276     const gchar *account_path,
1277     const GError *error,
1278     gpointer user_data,
1279     GObject *weak_object)
1280 {
1281   TpAccountRequest *self = TP_ACCOUNT_REQUEST (weak_object);
1282   TpAccountRequestPrivate *priv = self->priv;
1283   GError *e = NULL;
1284   TpAccount *account;
1285   GArray *features;
1286 
1287   if (error != NULL)
1288     {
1289       DEBUG ("failed to create account: %s", error->message);
1290       g_simple_async_result_set_from_error (priv->result, error);
1291       g_simple_async_result_complete (priv->result);
1292       g_clear_object (&priv->result);
1293       return;
1294     }
1295 
1296   priv->created = TRUE;
1297 
1298   account = tp_simple_client_factory_ensure_account (
1299       tp_proxy_get_factory (proxy), account_path, NULL, &e);
1300 
1301   if (account == NULL)
1302     {
1303       g_simple_async_result_take_error (priv->result, e);
1304       g_simple_async_result_complete (priv->result);
1305       g_clear_object (&priv->result);
1306       return;
1307     }
1308 
1309   /* Give account's ref to the result */
1310   g_simple_async_result_set_op_res_gpointer (priv->result, account,
1311       g_object_unref);
1312 
1313   features = tp_simple_client_factory_dup_account_features (
1314       tp_proxy_get_factory (proxy), account);
1315 
1316   tp_proxy_prepare_async (account, (GQuark *) features->data,
1317       tp_account_request_account_prepared_cb, self);
1318 
1319   g_array_unref (features);
1320 }
1321 
1322 /**
1323  * tp_account_request_create_account_async:
1324  * @self: a #TpAccountRequest
1325  * @callback: a function to call when the account has been created
1326  * @user_data: user data to @callback
1327  *
1328  * Start an asynchronous operation to create the account @self on the
1329  * account manager.
1330  *
1331  * @callback will only be called when the newly created #TpAccount has
1332  * the %TP_ACCOUNT_FEATURE_CORE feature ready on it, so when calling
1333  * tp_account_request_create_account_finish(), one can guarantee this
1334  * feature.
1335  *
1336  * Since: 0.19.1
1337  */
1338 void
tp_account_request_create_account_async(TpAccountRequest * self,GAsyncReadyCallback callback,gpointer user_data)1339 tp_account_request_create_account_async (TpAccountRequest *self,
1340     GAsyncReadyCallback callback,
1341     gpointer user_data)
1342 {
1343   TpAccountRequestPrivate *priv = self->priv;
1344 
1345   g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
1346 
1347   priv = self->priv;
1348 
1349   if (priv->result != NULL)
1350     {
1351       g_simple_async_report_error_in_idle (G_OBJECT (self),
1352           callback, user_data,
1353           TP_ERROR, TP_ERROR_BUSY,
1354           "An account creation operation has already been started on this "
1355           "account request");
1356       return;
1357     }
1358 
1359   if (priv->created)
1360     {
1361       g_simple_async_report_error_in_idle (G_OBJECT (self),
1362           callback, user_data,
1363           TP_ERROR, TP_ERROR_NOT_AVAILABLE,
1364           "This account has already been created");
1365       return;
1366     }
1367 
1368   priv->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1369       tp_account_request_create_account_async);
1370 
1371   tp_cli_account_manager_call_create_account (priv->account_manager,
1372       -1, priv->cm_name, priv->proto_name, priv->display_name,
1373       priv->parameters, priv->properties,
1374       tp_account_request_create_account_cb, NULL, NULL, G_OBJECT (self));
1375 }
1376 
1377 /**
1378  * tp_account_request_create_account_finish:
1379  * @self: a #TpAccountRequest
1380  * @result: a #GAsyncResult
1381  * @error: something
1382  *
1383  * Finishes an asynchronous account creation operation and returns a
1384  * new ref to a #TpAccount object. The returned account will have the
1385  * features listed in tp_simple_client_factory_dup_account_features()
1386  * (with the proxy factory from #TpAccountRequest:account-manager)
1387  * prepared on it.
1388  *
1389  * Returns: (transfer full): a new ref to a #TpAccount, or %NULL
1390  *
1391  * Since: 0.19.1
1392  */
1393 TpAccount *
tp_account_request_create_account_finish(TpAccountRequest * self,GAsyncResult * result,GError ** error)1394 tp_account_request_create_account_finish (TpAccountRequest *self,
1395     GAsyncResult *result,
1396     GError **error)
1397 {
1398   _tp_implement_finish_return_copy_pointer (self,
1399       tp_account_request_create_account_async, g_object_ref);
1400 }
1401