+/* Helper for server_side_source_remote_create_cb() */
+static void
+server_side_source_remote_create_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ESource *source;
+ AsyncContext *async_context;
+ GError *error = NULL;
+
+ source = E_SOURCE (source_object);
+ async_context = (AsyncContext *) user_data;
+
+ e_source_remote_create_finish (source, result, &error);
+
+ if (error != NULL)
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ else
+ e_dbus_source_remote_creatable_complete_create (
+ async_context->remote_creatable,
+ async_context->invocation);
+
+ async_context_free (async_context);
+}
+
+static gboolean
+server_side_source_remote_create_cb (EDBusSourceRemoteCreatable *interface,
+ GDBusMethodInvocation *invocation,
+ const gchar *uid,
+ const gchar *data,
+ ESource *source)
+{
+ EServerSideSource *server_side_source;
+ ESourceRegistryServer *server;
+ AsyncContext *async_context;
+ ESource *scratch_source;
+ GDBusObject *dbus_object;
+ EDBusSource *dbus_source;
+ GKeyFile *key_file;
+ GFile *file;
+ GError *error = NULL;
+
+ /* Create a new EServerSideSource from 'uid' and 'data' but
+ * DO NOT add it to the ESourceRegistryServer yet. It's up
+ * to the ECollectionBackend whether to use source as given
+ * or create its own equivalent EServerSideSource, possibly
+ * in response to a notification from a remote server. */
+
+ /* Validate the raw data. */
+ key_file = g_key_file_new ();
+ server_side_source_parse_data (key_file, data, strlen (data), &error);
+ g_key_file_free (key_file);
+
+ if (error != NULL) {
+ g_dbus_method_invocation_take_error (invocation, error);
+ return TRUE;
+ }
+
+ server_side_source = E_SERVER_SIDE_SOURCE (source);
+ server = e_server_side_source_get_server (server_side_source);
+
+ file = e_server_side_source_new_user_file (uid);
+ scratch_source = e_server_side_source_new (server, file, &error);
+ g_object_unref (file);
+
+ /* Sanity check. */
+ g_warn_if_fail (
+ ((scratch_source != NULL) && (error == NULL)) ||
+ ((scratch_source == NULL) && (error != NULL)));
+
+ if (error != NULL) {
+ g_dbus_method_invocation_take_error (invocation, error);
+ return TRUE;
+ }
+
+ dbus_object = e_source_ref_dbus_object (scratch_source);
+ dbus_source = e_dbus_object_get_source (E_DBUS_OBJECT (dbus_object));
+
+ e_dbus_source_set_data (dbus_source, data);
+
+ g_object_unref (dbus_object);
+ g_object_unref (dbus_source);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->remote_creatable = g_object_ref (interface);
+ async_context->invocation = g_object_ref (invocation);
+
+ e_source_remote_create (
+ source, scratch_source, NULL,
+ server_side_source_remote_create_done_cb,
+ async_context);
+
+ g_object_unref (scratch_source);
+
+ return TRUE;
+}
+
+/* Helper for server_side_source_remote_delete_cb() */
+static void
+server_side_source_remote_delete_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ESource *source;
+ AsyncContext *async_context;
+ GError *error = NULL;
+
+ source = E_SOURCE (source_object);
+ async_context = (AsyncContext *) user_data;
+
+ e_source_remote_delete_finish (source, result, &error);
+
+ if (error != NULL)
+ g_dbus_method_invocation_take_error (
+ async_context->invocation, error);
+ else
+ e_dbus_source_remote_deletable_complete_delete (
+ async_context->remote_deletable,
+ async_context->invocation);
+
+ async_context_free (async_context);
+}
+
+static gboolean
+server_side_source_remote_delete_cb (EDBusSourceRemoteDeletable *interface,
+ GDBusMethodInvocation *invocation,
+ ESource *source)
+{
+ AsyncContext *async_context;
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->remote_deletable = g_object_ref (interface);
+ async_context->invocation = g_object_ref (invocation);
+
+ e_source_remote_delete (
+ source, NULL,
+ server_side_source_remote_delete_done_cb,
+ async_context);
+
+ return TRUE;
+}
+