|
Packit |
79f644 |
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
Packit |
79f644 |
/*
|
|
Packit |
79f644 |
* Copyright © 2011 – 2017 Red Hat, Inc.
|
|
Packit |
79f644 |
*
|
|
Packit |
79f644 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
79f644 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
79f644 |
* License as published by the Free Software Foundation; either
|
|
Packit |
79f644 |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
79f644 |
*
|
|
Packit |
79f644 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
79f644 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
79f644 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
79f644 |
* Lesser General Public License for more details.
|
|
Packit |
79f644 |
*
|
|
Packit |
79f644 |
* You should have received a copy of the GNU Lesser General
|
|
Packit |
79f644 |
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
79f644 |
*/
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
#include "config.h"
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
#include <errno.h>
|
|
Packit |
79f644 |
#include <string.h>
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
#include <gio/gio.h>
|
|
Packit |
79f644 |
#include <glib/gi18n.h>
|
|
Packit |
79f644 |
#include <rest/rest-proxy.h>
|
|
Packit |
79f644 |
#include <libsoup/soup.h>
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
#include "goadaemon.h"
|
|
Packit |
79f644 |
#include "goa/goa.h"
|
|
Packit |
79f644 |
#include "goabackend/goabackend.h"
|
|
Packit |
79f644 |
#include "goabackend/goaprovider-priv.h"
|
|
Packit |
79f644 |
#include "goabackend/goautils.h"
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
struct _GoaDaemon
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GObject parent_instance;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
GDBusConnection *connection;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
GFileMonitor *home_conf_file_monitor;
|
|
Packit |
79f644 |
GFileMonitor *template_file_monitor;
|
|
Packit |
79f644 |
gchar *home_conf_file_path;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
GNetworkMonitor *network_monitor;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
GDBusObjectManagerServer *object_manager;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
GoaManager *manager;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
GQueue *ensure_credentials_queue;
|
|
Packit |
79f644 |
gboolean ensure_credentials_running;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
guint config_timeout_id;
|
|
Packit |
79f644 |
guint credentials_timeout_id;
|
|
Packit |
79f644 |
};
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
enum
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
PROP_0,
|
|
Packit |
79f644 |
PROP_CONNECTION
|
|
Packit |
79f644 |
};
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void on_file_monitor_changed (GFileMonitor *monitor,
|
|
Packit |
79f644 |
GFile *file,
|
|
Packit |
79f644 |
GFile *other_file,
|
|
Packit |
79f644 |
GFileMonitorEvent event_type,
|
|
Packit |
79f644 |
gpointer user_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean on_manager_handle_add_account (GoaManager *object,
|
|
Packit |
79f644 |
GDBusMethodInvocation *invocation,
|
|
Packit |
79f644 |
const gchar *provider_type,
|
|
Packit |
79f644 |
const gchar *identity,
|
|
Packit |
79f644 |
const gchar *presentation_identity,
|
|
Packit |
79f644 |
GVariant *credentials,
|
|
Packit |
79f644 |
GVariant *details,
|
|
Packit |
79f644 |
gpointer user_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean on_account_handle_remove (GoaAccount *account,
|
|
Packit |
79f644 |
GDBusMethodInvocation *invocation,
|
|
Packit |
79f644 |
gpointer user_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean on_account_handle_ensure_credentials (GoaAccount *account,
|
|
Packit |
79f644 |
GDBusMethodInvocation *invocation,
|
|
Packit |
79f644 |
gpointer user_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void ensure_credentials_queue_check (GoaDaemon *self);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void goa_daemon_check_credentials (GoaDaemon *self);
|
|
Packit |
79f644 |
static void goa_daemon_reload_configuration (GoaDaemon *self);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
G_DEFINE_TYPE (GoaDaemon, goa_daemon, G_TYPE_OBJECT);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
typedef struct
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GError **error;
|
|
Packit |
79f644 |
GList **out_providers;
|
|
Packit |
79f644 |
GMainLoop *loop;
|
|
Packit |
79f644 |
gboolean op_res;
|
|
Packit |
79f644 |
} GetAllSyncData;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
get_all_providers_sync_cb (GObject *source_object,
|
|
Packit |
79f644 |
GAsyncResult *res,
|
|
Packit |
79f644 |
gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GetAllSyncData *data = (GetAllSyncData *) user_data;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
data->op_res = goa_provider_get_all_finish (data->out_providers, res, data->error);
|
|
Packit |
79f644 |
g_main_loop_quit (data->loop);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean
|
|
Packit |
79f644 |
get_all_providers_sync (GCancellable *cancellable,
|
|
Packit |
79f644 |
GList **out_providers,
|
|
Packit |
79f644 |
GError **error)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GetAllSyncData data;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
data.error = error;
|
|
Packit |
79f644 |
data.out_providers = out_providers;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* HACK: Since telepathy-glib doesn't use the thread-default
|
|
Packit |
79f644 |
* GMainContext for invoking the asynchronous callbacks, we can't
|
|
Packit |
79f644 |
* push a new GMainContext here.
|
|
Packit |
79f644 |
*/
|
|
Packit |
79f644 |
data.loop = g_main_loop_new (NULL, FALSE);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
goa_provider_get_all (get_all_providers_sync_cb, &data);
|
|
Packit |
79f644 |
g_main_loop_run (data.loop);
|
|
Packit |
79f644 |
g_main_loop_unref (data.loop);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
return data.op_res;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
goa_daemon_constructed (GObject *object)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaDaemon *self = GOA_DAEMON (object);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
G_OBJECT_CLASS (goa_daemon_parent_class)->constructed (object);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* prime the list of accounts */
|
|
Packit |
79f644 |
goa_daemon_reload_configuration (self);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* Export objects */
|
|
Packit |
79f644 |
g_dbus_object_manager_server_set_connection (self->object_manager, self->connection);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
goa_daemon_finalize (GObject *object)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaDaemon *self = GOA_DAEMON (object);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (self->config_timeout_id != 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_source_remove (self->config_timeout_id);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (self->credentials_timeout_id != 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_source_remove (self->credentials_timeout_id);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (self->home_conf_file_monitor != NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_signal_handlers_disconnect_by_func (self->home_conf_file_monitor, on_file_monitor_changed, self);
|
|
Packit |
79f644 |
g_object_unref (self->home_conf_file_monitor);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (self->template_file_monitor != NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_signal_handlers_disconnect_by_func (self->template_file_monitor, on_file_monitor_changed, self);
|
|
Packit |
79f644 |
g_object_unref (self->template_file_monitor);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_free (self->home_conf_file_path);
|
|
Packit |
79f644 |
g_object_unref (self->manager);
|
|
Packit |
79f644 |
g_object_unref (self->object_manager);
|
|
Packit |
79f644 |
g_object_unref (self->connection);
|
|
Packit |
79f644 |
g_queue_free_full (self->ensure_credentials_queue, g_object_unref);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
G_OBJECT_CLASS (goa_daemon_parent_class)->finalize (object);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
goa_daemon_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaDaemon *self = GOA_DAEMON (object);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
switch (prop_id)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
case PROP_CONNECTION:
|
|
Packit |
79f644 |
self->connection = G_DBUS_CONNECTION (g_value_dup_object (value));
|
|
Packit |
79f644 |
break;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
default:
|
|
Packit |
79f644 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
Packit |
79f644 |
break;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static GFileMonitor *
|
|
Packit |
79f644 |
create_monitor (const gchar *path, gboolean is_dir)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GFile *file;
|
|
Packit |
79f644 |
GFileMonitor *monitor;
|
|
Packit |
79f644 |
GError *error;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
file = g_file_new_for_path (path);
|
|
Packit |
79f644 |
if (is_dir)
|
|
Packit |
79f644 |
monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, &error);
|
|
Packit |
79f644 |
else
|
|
Packit |
79f644 |
monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (monitor == NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Error monitoring %s at %s: %s (%s, %d)",
|
|
Packit |
79f644 |
is_dir ? "directory" : "file",
|
|
Packit |
79f644 |
path,
|
|
Packit |
79f644 |
error->message, g_quark_to_string (error->domain), error->code);
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
g_object_unref (file);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
return monitor;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean
|
|
Packit |
79f644 |
on_config_file_monitor_timeout (gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaDaemon *self = GOA_DAEMON (user_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
self->config_timeout_id = 0;
|
|
Packit |
79f644 |
g_debug ("Reloading configuration files");
|
|
Packit |
79f644 |
goa_daemon_reload_configuration (self);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
return G_SOURCE_REMOVE;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
on_file_monitor_changed (GFileMonitor *monitor,
|
|
Packit |
79f644 |
GFile *file,
|
|
Packit |
79f644 |
GFile *other_file,
|
|
Packit |
79f644 |
GFileMonitorEvent event_type,
|
|
Packit |
79f644 |
gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaDaemon *self = GOA_DAEMON (user_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (self->config_timeout_id == 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
self->config_timeout_id = g_timeout_add (200, on_config_file_monitor_timeout, self);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean
|
|
Packit |
79f644 |
on_check_credentials_timeout (gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaDaemon *self = GOA_DAEMON (user_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
self->credentials_timeout_id = 0;
|
|
Packit |
79f644 |
g_debug ("Calling EnsureCredentials due to network changes");
|
|
Packit |
79f644 |
goa_daemon_check_credentials (self);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
return G_SOURCE_REMOVE;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
queue_check_credentials (GoaDaemon *self)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
if (self->credentials_timeout_id != 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_source_remove (self->credentials_timeout_id);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
self->credentials_timeout_id = g_timeout_add_seconds (1, on_check_credentials_timeout, self);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
on_network_monitor_network_changed (GoaDaemon *self, gboolean available)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
queue_check_credentials (self);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
goa_daemon_init (GoaDaemon *self)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
static volatile GQuark goa_error_domain = 0;
|
|
Packit |
79f644 |
GError *error;
|
|
Packit |
79f644 |
GList *l;
|
|
Packit |
79f644 |
GList *providers = NULL;
|
|
Packit |
79f644 |
GoaObjectSkeleton *object;
|
|
Packit |
79f644 |
gchar *path;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* this will force associating errors in the GOA_ERROR error domain
|
|
Packit |
79f644 |
* with org.freedesktop.Goa.Error.* errors via g_dbus_error_register_error_domain().
|
|
Packit |
79f644 |
*/
|
|
Packit |
79f644 |
goa_error_domain = GOA_ERROR;
|
|
Packit |
79f644 |
goa_error_domain; /* shut up -Wunused-but-set-variable */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!get_all_providers_sync (NULL, &providers, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Unable to get the list of providers: %s (%s, %d)",
|
|
Packit |
79f644 |
error->message,
|
|
Packit |
79f644 |
g_quark_to_string (error->domain),
|
|
Packit |
79f644 |
error->code);
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
for (l = providers; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaProvider *provider = GOA_PROVIDER (l->data);
|
|
Packit |
79f644 |
goa_provider_initialize (provider);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* Create object manager */
|
|
Packit |
79f644 |
self->object_manager = g_dbus_object_manager_server_new ("/org/gnome/OnlineAccounts");
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* Create and export Manager */
|
|
Packit |
79f644 |
self->manager = goa_manager_skeleton_new ();
|
|
Packit |
79f644 |
g_signal_connect (self->manager,
|
|
Packit |
79f644 |
"handle-add-account",
|
|
Packit |
79f644 |
G_CALLBACK (on_manager_handle_add_account),
|
|
Packit |
79f644 |
self);
|
|
Packit |
79f644 |
object = goa_object_skeleton_new ("/org/gnome/OnlineAccounts/Manager");
|
|
Packit |
79f644 |
goa_object_skeleton_set_manager (object, self->manager);
|
|
Packit |
79f644 |
g_dbus_object_manager_server_export (self->object_manager, G_DBUS_OBJECT_SKELETON (object));
|
|
Packit |
79f644 |
g_object_unref (object);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
self->home_conf_file_path = g_strdup_printf ("%s/goa-1.0/accounts.conf", g_get_user_config_dir ());
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* create ~/.config/goa-1.0 directory */
|
|
Packit |
79f644 |
path = g_path_get_dirname (self->home_conf_file_path);
|
|
Packit |
79f644 |
if (g_mkdir_with_parents (path, 0755) != 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Error creating directory %s: %s", path, strerror (errno));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
g_free (path);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* set up file monitoring */
|
|
Packit |
79f644 |
self->home_conf_file_monitor = create_monitor (self->home_conf_file_path, FALSE);
|
|
Packit |
79f644 |
if (self->home_conf_file_monitor != NULL)
|
|
Packit |
79f644 |
g_signal_connect (self->home_conf_file_monitor, "changed", G_CALLBACK (on_file_monitor_changed), self);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (GOA_TEMPLATE_FILE != NULL && GOA_TEMPLATE_FILE[0] != '\0')
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
self->template_file_monitor = create_monitor (GOA_TEMPLATE_FILE, FALSE);
|
|
Packit |
79f644 |
if (self->template_file_monitor != NULL)
|
|
Packit |
79f644 |
g_signal_connect (self->template_file_monitor, "changed", G_CALLBACK (on_file_monitor_changed), self);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
self->network_monitor = g_network_monitor_get_default ();
|
|
Packit |
79f644 |
g_signal_connect_object (self->network_monitor,
|
|
Packit |
79f644 |
"network-changed",
|
|
Packit |
79f644 |
G_CALLBACK (on_network_monitor_network_changed),
|
|
Packit |
79f644 |
self,
|
|
Packit |
79f644 |
G_CONNECT_SWAPPED);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
self->ensure_credentials_queue = g_queue_new ();
|
|
Packit |
79f644 |
queue_check_credentials (self);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_list_free_full (providers, g_object_unref);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
goa_daemon_class_init (GoaDaemonClass *klass)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GObjectClass *gobject_class;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit |
79f644 |
gobject_class->constructed = goa_daemon_constructed;
|
|
Packit |
79f644 |
gobject_class->finalize = goa_daemon_finalize;
|
|
Packit |
79f644 |
gobject_class->set_property = goa_daemon_set_property;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_object_class_install_property (gobject_class,
|
|
Packit |
79f644 |
PROP_CONNECTION,
|
|
Packit |
79f644 |
g_param_spec_object ("connection",
|
|
Packit |
79f644 |
"GDBusConnection object",
|
|
Packit |
79f644 |
"A connection to a message bus",
|
|
Packit |
79f644 |
G_TYPE_DBUS_CONNECTION,
|
|
Packit |
79f644 |
G_PARAM_CONSTRUCT_ONLY |
|
|
Packit |
79f644 |
G_PARAM_STATIC_STRINGS |
|
|
Packit |
79f644 |
G_PARAM_WRITABLE));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
GoaDaemon *
|
|
Packit |
79f644 |
goa_daemon_new (GDBusConnection *connection)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
|
|
Packit |
79f644 |
return GOA_DAEMON (g_object_new (GOA_TYPE_DAEMON, "connection", connection, NULL));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
diff_sorted_lists (GList *list1,
|
|
Packit |
79f644 |
GList *list2,
|
|
Packit |
79f644 |
GCompareFunc compare,
|
|
Packit |
79f644 |
GList **out_added,
|
|
Packit |
79f644 |
GList **out_removed,
|
|
Packit |
79f644 |
GList **out_unchanged)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GList *added = NULL;
|
|
Packit |
79f644 |
GList *removed = NULL;
|
|
Packit |
79f644 |
GList *unchanged = NULL;
|
|
Packit |
79f644 |
gint order;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
while (list1 != NULL && list2 != NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
order = (*compare) (list1->data, list2->data);
|
|
Packit |
79f644 |
if (order < 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
removed = g_list_prepend (removed, list1->data);
|
|
Packit |
79f644 |
list1 = list1->next;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else if (order > 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
added = g_list_prepend (added, list2->data);
|
|
Packit |
79f644 |
list2 = list2->next;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else
|
|
Packit |
79f644 |
{ /* same item */
|
|
Packit |
79f644 |
unchanged = g_list_prepend (unchanged, list1->data);
|
|
Packit |
79f644 |
list1 = list1->next;
|
|
Packit |
79f644 |
list2 = list2->next;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
while (list1 != NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
removed = g_list_prepend (removed, list1->data);
|
|
Packit |
79f644 |
list1 = list1->next;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
while (list2 != NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
added = g_list_prepend (added, list2->data);
|
|
Packit |
79f644 |
list2 = list2->next;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (out_added != NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
*out_added = added;
|
|
Packit |
79f644 |
added = NULL;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (out_removed != NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
*out_removed = removed;
|
|
Packit |
79f644 |
removed = NULL;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (out_unchanged != NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
*out_unchanged = unchanged;
|
|
Packit |
79f644 |
unchanged = NULL;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_list_free (added);
|
|
Packit |
79f644 |
g_list_free (removed);
|
|
Packit |
79f644 |
g_list_free (unchanged);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static const gchar *
|
|
Packit |
79f644 |
account_group_to_id (const gchar *group)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_return_val_if_fail (g_str_has_prefix (group, "Account "), NULL);
|
|
Packit |
79f644 |
return group + sizeof "Account " - 1;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gchar *
|
|
Packit |
79f644 |
account_object_path_to_group (const gchar *object_path)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_return_val_if_fail (g_str_has_prefix (object_path, "/org/gnome/OnlineAccounts/Accounts/"), NULL);
|
|
Packit |
79f644 |
return g_strdup_printf ("Account %s", object_path + sizeof "/org/gnome/OnlineAccounts/Accounts/" - 1);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static const gchar *
|
|
Packit |
79f644 |
template_group_to_id (const gchar *group)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_return_val_if_fail (g_str_has_prefix (group, "Template "), NULL);
|
|
Packit |
79f644 |
return group + sizeof "Template " - 1;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
typedef struct
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GKeyFile *key_file;
|
|
Packit |
79f644 |
gchar *path;
|
|
Packit |
79f644 |
} KeyFileData;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
key_file_data_free (KeyFileData *data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_key_file_unref (data->key_file);
|
|
Packit |
79f644 |
g_free (data->path);
|
|
Packit |
79f644 |
g_slice_free (KeyFileData, data);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static KeyFileData *
|
|
Packit |
79f644 |
key_file_data_new (GKeyFile *key_file,
|
|
Packit |
79f644 |
const gchar *path)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
KeyFileData *data;
|
|
Packit |
79f644 |
data = g_slice_new (KeyFileData);
|
|
Packit |
79f644 |
data->key_file = g_key_file_ref (key_file);
|
|
Packit |
79f644 |
data->path = g_strdup (path);
|
|
Packit |
79f644 |
return data;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
add_config_file (GoaDaemon *self,
|
|
Packit |
79f644 |
const gchar *path,
|
|
Packit |
79f644 |
GHashTable *group_name_to_key_file_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GKeyFile *key_file;
|
|
Packit |
79f644 |
GError *error;
|
|
Packit |
79f644 |
gboolean needs_update = FALSE;
|
|
Packit |
79f644 |
gchar **groups;
|
|
Packit |
79f644 |
const char *guid;
|
|
Packit |
79f644 |
gsize num_groups;
|
|
Packit |
79f644 |
guint n;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
key_file = g_key_file_new ();
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!g_key_file_load_from_file (key_file,
|
|
Packit |
79f644 |
path,
|
|
Packit |
79f644 |
G_KEY_FILE_NONE,
|
|
Packit |
79f644 |
&error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Error loading %s: %s (%s, %d)",
|
|
Packit |
79f644 |
path,
|
|
Packit |
79f644 |
error->message, g_quark_to_string (error->domain), error->code);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
guid = g_dbus_connection_get_guid (self->connection);
|
|
Packit |
79f644 |
groups = g_key_file_get_groups (key_file, &num_groups);
|
|
Packit |
79f644 |
for (n = 0; n < num_groups; n++)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
if (g_str_has_prefix (groups[n], "Account "))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
gboolean is_temporary;
|
|
Packit |
79f644 |
char *session_id;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
is_temporary = g_key_file_get_boolean (key_file,
|
|
Packit |
79f644 |
groups[n],
|
|
Packit |
79f644 |
"IsTemporary",
|
|
Packit |
79f644 |
NULL);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (is_temporary)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
session_id = g_key_file_get_string (key_file,
|
|
Packit |
79f644 |
groups[n],
|
|
Packit |
79f644 |
"SessionId",
|
|
Packit |
79f644 |
NULL);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* discard temporary accounts from older sessions */
|
|
Packit |
79f644 |
if (session_id != NULL &&
|
|
Packit |
79f644 |
g_strcmp0 (session_id, guid) != 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaProvider *provider = NULL;
|
|
Packit |
79f644 |
const gchar *id;
|
|
Packit |
79f644 |
gchar *provider_type = NULL;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_debug ("ignoring account \"%s\" in file %s because it's stale",
|
|
Packit |
79f644 |
groups[n], path);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
id = account_group_to_id (groups[n]);
|
|
Packit |
79f644 |
if (id == NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Unable to get account ID from group: %s", groups[n]);
|
|
Packit |
79f644 |
goto cleanup_and_continue;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
provider_type = g_key_file_get_string (key_file, groups[n], "Provider", NULL);
|
|
Packit |
79f644 |
if (provider_type != NULL)
|
|
Packit |
79f644 |
provider = goa_provider_get_for_provider_type (provider_type);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (provider == NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Unsupported account type %s for ID %s (no provider)", provider_type, id);
|
|
Packit |
79f644 |
goto cleanup_and_continue;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
needs_update = g_key_file_remove_group (key_file, groups[n], NULL);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!goa_utils_delete_credentials_for_id_sync (provider, id, NULL, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Unable to clean-up stale keyring entries: %s", error->message);
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
goto cleanup_and_continue;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
cleanup_and_continue:
|
|
Packit |
79f644 |
g_clear_object (&provider);
|
|
Packit |
79f644 |
g_free (groups[n]);
|
|
Packit |
79f644 |
g_free (provider_type);
|
|
Packit |
79f644 |
g_free (session_id);
|
|
Packit |
79f644 |
continue;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
g_free (session_id);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
needs_update = g_key_file_remove_key (key_file, groups[n], "SessionId", NULL);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_hash_table_insert (group_name_to_key_file_data,
|
|
Packit |
79f644 |
groups[n], /* steals string */
|
|
Packit |
79f644 |
key_file_data_new (key_file, path));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else if (g_str_has_prefix (groups[n], "Template "))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_hash_table_insert (group_name_to_key_file_data,
|
|
Packit |
79f644 |
groups[n], /* steals string */
|
|
Packit |
79f644 |
key_file_data_new (key_file, path));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Unexpected group \"%s\" in file %s", groups[n], path);
|
|
Packit |
79f644 |
g_free (groups[n]);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
g_free (groups);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (needs_update)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!g_key_file_save_to_file (key_file, path, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_prefix_error (&error, "Error writing key-value-file %s: ", path);
|
|
Packit |
79f644 |
g_warning ("%s (%s, %d)", error->message, g_quark_to_string (error->domain), error->code);
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
out:
|
|
Packit |
79f644 |
g_key_file_unref (key_file);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* returns FALSE if object is not (or no longer) valid */
|
|
Packit |
79f644 |
static gboolean
|
|
Packit |
79f644 |
update_account_object (GoaDaemon *self,
|
|
Packit |
79f644 |
GoaObjectSkeleton *object,
|
|
Packit |
79f644 |
const gchar *path,
|
|
Packit |
79f644 |
const gchar *group,
|
|
Packit |
79f644 |
GKeyFile *key_file,
|
|
Packit |
79f644 |
gboolean just_added)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaAccount *account = NULL;
|
|
Packit |
79f644 |
GoaProvider *provider = NULL;
|
|
Packit |
79f644 |
gboolean is_locked;
|
|
Packit |
79f644 |
gboolean is_temporary;
|
|
Packit |
79f644 |
gboolean ret = FALSE;
|
|
Packit |
79f644 |
gchar *identity = NULL;
|
|
Packit |
79f644 |
gchar *presentation_identity;
|
|
Packit |
79f644 |
gchar *type = NULL;
|
|
Packit |
79f644 |
gchar *name = NULL;
|
|
Packit |
79f644 |
GIcon *icon = NULL;
|
|
Packit |
79f644 |
gchar *serialized_icon = NULL;
|
|
Packit |
79f644 |
GError *error;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_return_val_if_fail (GOA_IS_DAEMON (self), FALSE);
|
|
Packit |
79f644 |
g_return_val_if_fail (G_IS_DBUS_OBJECT_SKELETON (object), FALSE);
|
|
Packit |
79f644 |
g_return_val_if_fail (group != NULL, FALSE);
|
|
Packit |
79f644 |
g_return_val_if_fail (key_file != NULL, FALSE);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_debug ("updating %s %d", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)), just_added);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
type = g_key_file_get_string (key_file, group, "Provider", NULL);
|
|
Packit |
79f644 |
identity = g_key_file_get_string (key_file, group, "Identity", NULL);
|
|
Packit |
79f644 |
presentation_identity = g_key_file_get_string (key_file, group, "PresentationIdentity", NULL);
|
|
Packit |
79f644 |
is_locked = g_key_file_get_boolean (key_file, group, "IsLocked", NULL);
|
|
Packit |
79f644 |
is_temporary = g_key_file_get_boolean (key_file, group, "IsTemporary", NULL);
|
|
Packit |
79f644 |
if (just_added)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
account = goa_account_skeleton_new ();
|
|
Packit |
79f644 |
goa_object_skeleton_set_account (object, account);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
account = goa_object_get_account (GOA_OBJECT (object));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
provider = goa_provider_get_for_provider_type (type);
|
|
Packit |
79f644 |
if (provider == NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Unsupported account type %s for identity %s (no provider)", type, identity);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
goa_account_set_id (account, g_strrstr (g_dbus_object_get_object_path (G_DBUS_OBJECT (object)), "/") + 1);
|
|
Packit |
79f644 |
goa_account_set_provider_type (account, type);
|
|
Packit |
79f644 |
goa_account_set_identity (account, identity);
|
|
Packit |
79f644 |
goa_account_set_presentation_identity (account, presentation_identity);
|
|
Packit |
79f644 |
goa_account_set_is_locked (account, is_locked);
|
|
Packit |
79f644 |
goa_account_set_is_temporary (account, is_temporary);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!goa_provider_build_object (provider, object, key_file, group, self->connection, just_added, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Error parsing account: %s (%s, %d)",
|
|
Packit |
79f644 |
error->message, g_quark_to_string (error->domain), error->code);
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
name = goa_provider_get_provider_name (provider, GOA_OBJECT (object));
|
|
Packit |
79f644 |
goa_account_set_provider_name (account, name);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
icon = goa_provider_get_provider_icon (provider, GOA_OBJECT (object));
|
|
Packit |
79f644 |
serialized_icon = g_icon_to_string (icon);
|
|
Packit |
79f644 |
goa_account_set_provider_icon (account, serialized_icon);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
ret = TRUE;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
out:
|
|
Packit |
79f644 |
g_free (serialized_icon);
|
|
Packit |
79f644 |
g_clear_object (&icon);
|
|
Packit |
79f644 |
g_free (name);
|
|
Packit |
79f644 |
g_clear_object (&provider);
|
|
Packit |
79f644 |
g_clear_object (&account);
|
|
Packit |
79f644 |
g_free (type);
|
|
Packit |
79f644 |
g_free (identity);
|
|
Packit |
79f644 |
g_free (presentation_identity);
|
|
Packit |
79f644 |
return ret;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
process_config_entries (GoaDaemon *self,
|
|
Packit |
79f644 |
GHashTable *group_name_to_key_file_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GHashTableIter iter;
|
|
Packit |
79f644 |
KeyFileData *key_file_data;
|
|
Packit |
79f644 |
GList *existing_object_paths = NULL;
|
|
Packit |
79f644 |
GList *config_object_paths = NULL;
|
|
Packit |
79f644 |
GList *added;
|
|
Packit |
79f644 |
GList *removed;
|
|
Packit |
79f644 |
GList *unchanged;
|
|
Packit |
79f644 |
GList *l;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GList *existing_objects;
|
|
Packit |
79f644 |
existing_objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self->object_manager));
|
|
Packit |
79f644 |
for (l = existing_objects; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaObject *object = GOA_OBJECT (l->data);
|
|
Packit |
79f644 |
const gchar *object_path;
|
|
Packit |
79f644 |
object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
|
|
Packit |
79f644 |
if (g_str_has_prefix (object_path, "/org/gnome/OnlineAccounts/Accounts/"))
|
|
Packit |
79f644 |
existing_object_paths = g_list_prepend (existing_object_paths, g_strdup (object_path));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
g_list_free_full (existing_objects, g_object_unref);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
const gchar *group;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_hash_table_iter_init (&iter, group_name_to_key_file_data);
|
|
Packit |
79f644 |
while (g_hash_table_iter_next (&iter, (gpointer*) &group, (gpointer*) &key_file_data))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
const gchar *id;
|
|
Packit |
79f644 |
gchar *object_path;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (!g_str_has_prefix (group, "Account "))
|
|
Packit |
79f644 |
continue;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
id = account_group_to_id (group);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* create and validate object path */
|
|
Packit |
79f644 |
object_path = g_strdup_printf ("/org/gnome/OnlineAccounts/Accounts/%s", id);
|
|
Packit |
79f644 |
if (strstr (id, "/") != NULL || !g_variant_is_object_path (object_path))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("`%s' is not a valid account identifier", group);
|
|
Packit |
79f644 |
g_free (object_path);
|
|
Packit |
79f644 |
continue;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
/* steals object_path variable */
|
|
Packit |
79f644 |
config_object_paths = g_list_prepend (config_object_paths, object_path);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
existing_object_paths = g_list_sort (existing_object_paths, (GCompareFunc) g_strcmp0);
|
|
Packit |
79f644 |
config_object_paths = g_list_sort (config_object_paths, (GCompareFunc) g_strcmp0);
|
|
Packit |
79f644 |
diff_sorted_lists (existing_object_paths,
|
|
Packit |
79f644 |
config_object_paths,
|
|
Packit |
79f644 |
(GCompareFunc) g_strcmp0,
|
|
Packit |
79f644 |
&added,
|
|
Packit |
79f644 |
&removed,
|
|
Packit |
79f644 |
&unchanged);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
for (l = removed; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
const gchar *object_path = l->data;
|
|
Packit |
79f644 |
GoaObject *object;
|
|
Packit |
79f644 |
object = GOA_OBJECT (g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (self->object_manager), object_path));
|
|
Packit |
79f644 |
g_warn_if_fail (object != NULL);
|
|
Packit |
79f644 |
g_signal_handlers_disconnect_by_func (goa_object_peek_account (object),
|
|
Packit |
79f644 |
G_CALLBACK (on_account_handle_remove),
|
|
Packit |
79f644 |
self);
|
|
Packit |
79f644 |
g_object_unref (object);
|
|
Packit |
79f644 |
g_debug ("removing %s", object_path);
|
|
Packit |
79f644 |
g_warn_if_fail (g_dbus_object_manager_server_unexport (self->object_manager, object_path));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
for (l = added; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
const gchar *object_path = l->data;
|
|
Packit |
79f644 |
GoaObjectSkeleton *object;
|
|
Packit |
79f644 |
gchar *group;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_debug ("adding %s", object_path);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
group = account_object_path_to_group (object_path);
|
|
Packit |
79f644 |
key_file_data = g_hash_table_lookup (group_name_to_key_file_data, group);
|
|
Packit |
79f644 |
g_warn_if_fail (key_file_data != NULL);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
object = goa_object_skeleton_new (object_path);
|
|
Packit |
79f644 |
if (update_account_object (self,
|
|
Packit |
79f644 |
object,
|
|
Packit |
79f644 |
key_file_data->path,
|
|
Packit |
79f644 |
group,
|
|
Packit |
79f644 |
key_file_data->key_file,
|
|
Packit |
79f644 |
TRUE))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_dbus_object_manager_server_export (self->object_manager, G_DBUS_OBJECT_SKELETON (object));
|
|
Packit |
79f644 |
g_signal_connect (goa_object_peek_account (GOA_OBJECT (object)),
|
|
Packit |
79f644 |
"handle-remove",
|
|
Packit |
79f644 |
G_CALLBACK (on_account_handle_remove),
|
|
Packit |
79f644 |
self);
|
|
Packit |
79f644 |
g_signal_connect (goa_object_peek_account (GOA_OBJECT (object)),
|
|
Packit |
79f644 |
"handle-ensure-credentials",
|
|
Packit |
79f644 |
G_CALLBACK (on_account_handle_ensure_credentials),
|
|
Packit |
79f644 |
self);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
g_object_unref (object);
|
|
Packit |
79f644 |
g_free (group);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
for (l = unchanged; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
const gchar *object_path = l->data;
|
|
Packit |
79f644 |
GoaObject *object;
|
|
Packit |
79f644 |
gchar *group;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_debug ("unchanged %s", object_path);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
group = account_object_path_to_group (object_path);
|
|
Packit |
79f644 |
key_file_data = g_hash_table_lookup (group_name_to_key_file_data, group);
|
|
Packit |
79f644 |
g_warn_if_fail (key_file_data != NULL);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
object = GOA_OBJECT (g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (self->object_manager), object_path));
|
|
Packit |
79f644 |
g_warn_if_fail (object != NULL);
|
|
Packit |
79f644 |
if (!update_account_object (self,
|
|
Packit |
79f644 |
GOA_OBJECT_SKELETON (object),
|
|
Packit |
79f644 |
key_file_data->path,
|
|
Packit |
79f644 |
group,
|
|
Packit |
79f644 |
key_file_data->key_file,
|
|
Packit |
79f644 |
FALSE))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_signal_handlers_disconnect_by_func (goa_object_peek_account (object),
|
|
Packit |
79f644 |
G_CALLBACK (on_account_handle_remove),
|
|
Packit |
79f644 |
self);
|
|
Packit |
79f644 |
g_signal_handlers_disconnect_by_func (goa_object_peek_account (object),
|
|
Packit |
79f644 |
G_CALLBACK (on_account_handle_ensure_credentials),
|
|
Packit |
79f644 |
self);
|
|
Packit |
79f644 |
g_warn_if_fail (g_dbus_object_manager_server_unexport (self->object_manager, object_path));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
g_object_unref (object);
|
|
Packit |
79f644 |
g_free (group);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_list_free (removed);
|
|
Packit |
79f644 |
g_list_free (added);
|
|
Packit |
79f644 |
g_list_free (unchanged);
|
|
Packit |
79f644 |
g_list_free_full (existing_object_paths, g_free);
|
|
Packit |
79f644 |
g_list_free_full (config_object_paths, g_free);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gint
|
|
Packit |
79f644 |
compare_account_and_template_groups (const gchar *account_group, const gchar *template_group)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
const gchar *account_id;
|
|
Packit |
79f644 |
const gchar *template_id;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_return_val_if_fail (g_str_has_prefix (account_group, "Account "), 0);
|
|
Packit |
79f644 |
g_return_val_if_fail (g_str_has_prefix (template_group, "Template "), 0);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
account_id = account_group + sizeof "Account " - 1;
|
|
Packit |
79f644 |
template_id = template_group + sizeof "Template " - 1;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
return g_strcmp0 (account_id, template_id);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
process_template_entries (GoaDaemon *self,
|
|
Packit |
79f644 |
GHashTable *group_name_to_key_file_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GError *error;
|
|
Packit |
79f644 |
GHashTable *key_files_to_update = NULL;
|
|
Packit |
79f644 |
GHashTableIter iter;
|
|
Packit |
79f644 |
GKeyFile *home_conf_key_file = NULL;
|
|
Packit |
79f644 |
GKeyFile *key_file;
|
|
Packit |
79f644 |
KeyFileData *key_file_data;
|
|
Packit |
79f644 |
const gchar *group;
|
|
Packit |
79f644 |
const gchar *key_file_path;
|
|
Packit |
79f644 |
GList *config_object_groups = NULL;
|
|
Packit |
79f644 |
GList *config_template_groups = NULL;
|
|
Packit |
79f644 |
GList *added;
|
|
Packit |
79f644 |
GList *unchanged;
|
|
Packit |
79f644 |
GList *l;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
key_files_to_update = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_key_file_unref);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_hash_table_iter_init (&iter, group_name_to_key_file_data);
|
|
Packit |
79f644 |
while (g_hash_table_iter_next (&iter, (gpointer *) &group, (gpointer *) &key_file_data))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
if (home_conf_key_file == NULL && g_strcmp0 (key_file_data->path, self->home_conf_file_path) == 0)
|
|
Packit |
79f644 |
home_conf_key_file = g_key_file_ref (key_file_data->key_file);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (g_str_has_prefix (group, "Account "))
|
|
Packit |
79f644 |
config_object_groups = g_list_prepend (config_object_groups, g_strdup (group));
|
|
Packit |
79f644 |
else if (g_str_has_prefix (group, "Template "))
|
|
Packit |
79f644 |
config_template_groups = g_list_prepend (config_template_groups, g_strdup (group));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (home_conf_key_file == NULL)
|
|
Packit |
79f644 |
home_conf_key_file = g_key_file_new ();
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
config_object_groups = g_list_sort (config_object_groups, (GCompareFunc) g_strcmp0);
|
|
Packit |
79f644 |
config_template_groups = g_list_sort (config_template_groups, (GCompareFunc) g_strcmp0);
|
|
Packit |
79f644 |
diff_sorted_lists (config_object_groups,
|
|
Packit |
79f644 |
config_template_groups,
|
|
Packit |
79f644 |
(GCompareFunc) compare_account_and_template_groups,
|
|
Packit |
79f644 |
&added,
|
|
Packit |
79f644 |
NULL,
|
|
Packit |
79f644 |
&unchanged);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
for (l = added; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
gboolean needs_update;
|
|
Packit |
79f644 |
const gchar *id;
|
|
Packit |
79f644 |
const gchar *template_group = l->data;
|
|
Packit |
79f644 |
gchar *object_group = NULL;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
key_file_data = g_hash_table_lookup (group_name_to_key_file_data, template_group);
|
|
Packit |
79f644 |
g_assert_nonnull (key_file_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (goa_utils_keyfile_get_boolean (key_file_data->key_file, template_group, "ForceRemove"))
|
|
Packit |
79f644 |
continue;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_debug ("Adding from template %s", template_group);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
id = template_group_to_id (template_group);
|
|
Packit |
79f644 |
object_group = g_strdup_printf ("Account %s", id);
|
|
Packit |
79f644 |
g_warn_if_fail (!g_key_file_has_group (home_conf_key_file, object_group));
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
needs_update = goa_utils_keyfile_copy_group (key_file_data->key_file,
|
|
Packit |
79f644 |
template_group,
|
|
Packit |
79f644 |
home_conf_key_file,
|
|
Packit |
79f644 |
object_group);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (needs_update)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_key_file_set_boolean (home_conf_key_file, object_group, "IsLocked", TRUE);
|
|
Packit |
79f644 |
g_hash_table_insert (key_files_to_update,
|
|
Packit |
79f644 |
g_strdup (self->home_conf_file_path),
|
|
Packit |
79f644 |
g_key_file_ref (home_conf_key_file));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_free (object_group);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
for (l = unchanged; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
KeyFileData *object_key_file_data;
|
|
Packit |
79f644 |
KeyFileData *template_key_file_data;
|
|
Packit |
79f644 |
gboolean needs_update;
|
|
Packit |
79f644 |
const gchar *id;
|
|
Packit |
79f644 |
const gchar *object_group = l->data;
|
|
Packit |
79f644 |
gchar *template_group = NULL;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
object_key_file_data = g_hash_table_lookup (group_name_to_key_file_data, object_group);
|
|
Packit |
79f644 |
g_assert_nonnull (object_key_file_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_warn_if_fail (g_key_file_has_group (object_key_file_data->key_file, object_group));
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
id = account_group_to_id (object_group);
|
|
Packit |
79f644 |
template_group = g_strdup_printf ("Template %s", id);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
template_key_file_data = g_hash_table_lookup (group_name_to_key_file_data, template_group);
|
|
Packit |
79f644 |
g_assert_nonnull (template_key_file_data);
|
|
Packit |
79f644 |
g_assert_true (g_key_file_has_group (template_key_file_data->key_file, template_group));
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (goa_utils_keyfile_get_boolean (template_key_file_data->key_file, template_group, "ForceRemove"))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
gboolean removed;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_debug ("Template %s specifies ForceRemove, removing %s", template_group, object_group);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
needs_update = g_key_file_remove_group (object_key_file_data->key_file, object_group, &error);
|
|
Packit |
79f644 |
if (error != NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("Error removing group %s from %s: %s (%s, %d)",
|
|
Packit |
79f644 |
object_group,
|
|
Packit |
79f644 |
key_file_data->path,
|
|
Packit |
79f644 |
error->message,
|
|
Packit |
79f644 |
g_quark_to_string (error->domain),
|
|
Packit |
79f644 |
error->code);
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (needs_update)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_hash_table_insert (key_files_to_update,
|
|
Packit |
79f644 |
g_strdup (object_key_file_data->path),
|
|
Packit |
79f644 |
g_key_file_ref (object_key_file_data->key_file));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
removed = g_hash_table_remove (group_name_to_key_file_data, object_group);
|
|
Packit |
79f644 |
g_warn_if_fail (removed);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_debug ("Updating %s from template %s", object_group, template_group);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
needs_update = goa_utils_keyfile_copy_group (template_key_file_data->key_file,
|
|
Packit |
79f644 |
template_group,
|
|
Packit |
79f644 |
object_key_file_data->key_file,
|
|
Packit |
79f644 |
object_group);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (needs_update)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_key_file_set_boolean (home_conf_key_file, object_group, "IsLocked", TRUE);
|
|
Packit |
79f644 |
g_hash_table_insert (key_files_to_update,
|
|
Packit |
79f644 |
g_strdup (object_key_file_data->path),
|
|
Packit |
79f644 |
g_key_file_ref (object_key_file_data->key_file));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_free (template_group);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_hash_table_iter_init (&iter, key_files_to_update);
|
|
Packit |
79f644 |
while (g_hash_table_iter_next (&iter, (gpointer *) &key_file_path, (gpointer *) &key_file))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!g_key_file_save_to_file (key_file, key_file_path, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_prefix_error (&error, "Error writing key-value-file %s: ", key_file_path);
|
|
Packit |
79f644 |
g_warning ("%s (%s, %d)", error->message, g_quark_to_string (error->domain), error->code);
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_hash_table_unref (key_files_to_update);
|
|
Packit |
79f644 |
g_key_file_unref (home_conf_key_file);
|
|
Packit |
79f644 |
g_list_free (added);
|
|
Packit |
79f644 |
g_list_free (unchanged);
|
|
Packit |
79f644 |
g_list_free_full (config_object_groups, g_free);
|
|
Packit |
79f644 |
g_list_free_full (config_template_groups, g_free);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* <internal>
|
|
Packit |
79f644 |
* goa_daemon_reload_configuration:
|
|
Packit |
79f644 |
* @self: A #GoaDaemon
|
|
Packit |
79f644 |
*
|
|
Packit |
79f644 |
* Updates the accounts_objects member from stored configuration -
|
|
Packit |
79f644 |
* typically called at startup or when a change on the configuration
|
|
Packit |
79f644 |
* files has been detected.
|
|
Packit |
79f644 |
*/
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
goa_daemon_reload_configuration (GoaDaemon *self)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GHashTable *group_name_to_key_file_data;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
group_name_to_key_file_data = g_hash_table_new_full (g_str_hash,
|
|
Packit |
79f644 |
g_str_equal,
|
|
Packit |
79f644 |
g_free,
|
|
Packit |
79f644 |
(GDestroyNotify) key_file_data_free);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* Read the main user config file at $HOME/.config/goa-1.0/accounts.conf */
|
|
Packit |
79f644 |
add_config_file (self, self->home_conf_file_path, group_name_to_key_file_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (GOA_TEMPLATE_FILE != NULL && GOA_TEMPLATE_FILE[0] != '\0')
|
|
Packit |
79f644 |
add_config_file (self, GOA_TEMPLATE_FILE, group_name_to_key_file_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
process_template_entries (self, group_name_to_key_file_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* now process the group_name_to_key_file_data hash table */
|
|
Packit |
79f644 |
process_config_entries (self, group_name_to_key_file_data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_hash_table_unref (group_name_to_key_file_data);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gchar *
|
|
Packit |
79f644 |
generate_new_id (GoaDaemon *self)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
static guint counter = 0;
|
|
Packit |
79f644 |
GDateTime *dt;
|
|
Packit |
79f644 |
gchar *ret;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
dt = g_date_time_new_now_local ();
|
|
Packit |
79f644 |
ret = g_strdup_printf ("account_%" G_GINT64_FORMAT "_%u",
|
|
Packit |
79f644 |
g_date_time_to_unix (dt), /* seconds since Epoch */
|
|
Packit |
79f644 |
counter); /* avoids collisions */
|
|
Packit |
79f644 |
g_date_time_unref (dt);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
counter++;
|
|
Packit |
79f644 |
return ret;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
typedef struct
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaDaemon *daemon;
|
|
Packit |
79f644 |
GoaManager *manager;
|
|
Packit |
79f644 |
GDBusMethodInvocation *invocation;
|
|
Packit |
79f644 |
gchar *provider_type;
|
|
Packit |
79f644 |
gchar *identity;
|
|
Packit |
79f644 |
gchar *presentation_identity;
|
|
Packit |
79f644 |
GVariant *credentials;
|
|
Packit |
79f644 |
GVariant *details;
|
|
Packit |
79f644 |
} AddAccountData;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
get_all_providers_cb (GObject *source,
|
|
Packit |
79f644 |
GAsyncResult *res,
|
|
Packit |
79f644 |
gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
AddAccountData *data = user_data;
|
|
Packit |
79f644 |
GoaProvider *provider = NULL;
|
|
Packit |
79f644 |
GKeyFile *key_file = NULL;
|
|
Packit |
79f644 |
GError *error;
|
|
Packit |
79f644 |
GList *providers = NULL;
|
|
Packit |
79f644 |
GList *l;
|
|
Packit |
79f644 |
gchar *id = NULL;
|
|
Packit |
79f644 |
gchar *group = NULL;
|
|
Packit |
79f644 |
gchar *key_file_data = NULL;
|
|
Packit |
79f644 |
gsize length;
|
|
Packit |
79f644 |
gsize n_credentials;
|
|
Packit |
79f644 |
gchar *object_path = NULL;
|
|
Packit |
79f644 |
GVariantIter iter;
|
|
Packit |
79f644 |
const gchar *key;
|
|
Packit |
79f644 |
const gchar *value;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* TODO: could check for @type */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (!goa_provider_get_all_finish (&providers, res, NULL))
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
for (l = providers; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaProvider *p;
|
|
Packit |
79f644 |
const gchar *type;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
p = GOA_PROVIDER (l->data);
|
|
Packit |
79f644 |
type = goa_provider_get_provider_type (p);
|
|
Packit |
79f644 |
if (g_strcmp0 (type, data->provider_type) == 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
provider = p;
|
|
Packit |
79f644 |
break;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (provider == NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
error= NULL;
|
|
Packit |
79f644 |
g_set_error (&error,
|
|
Packit |
79f644 |
GOA_ERROR,
|
|
Packit |
79f644 |
GOA_ERROR_FAILED, /* TODO: more specific */
|
|
Packit |
79f644 |
_("Failed to find a provider for: %s"),
|
|
Packit |
79f644 |
data->provider_type);
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (data->invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
key_file = g_key_file_new ();
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!g_file_get_contents (data->daemon->home_conf_file_path,
|
|
Packit |
79f644 |
&key_file_data,
|
|
Packit |
79f644 |
&length,
|
|
Packit |
79f644 |
&error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
if (error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_prefix_error (&error, "Error loading file %s: ", data->daemon->home_conf_file_path);
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (data->invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
if (length > 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!g_key_file_load_from_data (key_file, key_file_data, length, G_KEY_FILE_KEEP_COMMENTS, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_prefix_error (&error, "Error parsing key-value-file %s: ", data->daemon->home_conf_file_path);
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (data->invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (!g_variant_lookup (data->details, "Id", "s", &id))
|
|
Packit |
79f644 |
id = generate_new_id (data->daemon);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
group = g_strdup_printf ("Account %s", id);
|
|
Packit |
79f644 |
g_key_file_set_string (key_file, group, "Provider", data->provider_type);
|
|
Packit |
79f644 |
g_key_file_set_string (key_file, group, "Identity", data->identity);
|
|
Packit |
79f644 |
g_key_file_set_string (key_file, group, "PresentationIdentity", data->presentation_identity);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_variant_iter_init (&iter, data->details);
|
|
Packit |
79f644 |
while (g_variant_iter_next (&iter, "{&s&s}", &key, &value))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
/* We treat IsTemporary special. If it's true we add in
|
|
Packit |
79f644 |
* the current session guid, so it can be ignored after
|
|
Packit |
79f644 |
* the session is over.
|
|
Packit |
79f644 |
*/
|
|
Packit |
79f644 |
if (g_strcmp0 (key, "IsTemporary") == 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
if (g_strcmp0 (value, "true") == 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
const char *guid;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
guid = g_dbus_connection_get_guid (data->daemon->connection);
|
|
Packit |
79f644 |
g_key_file_set_string (key_file, group, "SessionId", guid);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* Skip Id since we already handled it above. */
|
|
Packit |
79f644 |
if (g_strcmp0 (key, "Id") == 0)
|
|
Packit |
79f644 |
continue;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_key_file_set_string (key_file, group, key, value);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!g_key_file_save_to_file (key_file, data->daemon->home_conf_file_path, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_prefix_error (&error, "Error writing key-value-file %s: ", data->daemon->home_conf_file_path);
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (data->invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
n_credentials = g_variant_n_children (data->credentials);
|
|
Packit |
79f644 |
if (n_credentials > 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
/* We don't want to fail AddAccount if we could not store the
|
|
Packit |
79f644 |
* credentials in the keyring.
|
|
Packit |
79f644 |
*/
|
|
Packit |
79f644 |
goa_utils_store_credentials_for_id_sync (provider,
|
|
Packit |
79f644 |
id,
|
|
Packit |
79f644 |
data->credentials,
|
|
Packit |
79f644 |
NULL, /* GCancellable */
|
|
Packit |
79f644 |
NULL);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
goa_daemon_reload_configuration (data->daemon);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
object_path = g_strdup_printf ("/org/gnome/OnlineAccounts/Accounts/%s", id);
|
|
Packit |
79f644 |
goa_manager_complete_add_account (data->manager, data->invocation, object_path);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
out:
|
|
Packit |
79f644 |
g_free (object_path);
|
|
Packit |
79f644 |
g_list_free_full (providers, g_object_unref);
|
|
Packit |
79f644 |
g_free (key_file_data);
|
|
Packit |
79f644 |
g_free (group);
|
|
Packit |
79f644 |
g_free (id);
|
|
Packit |
79f644 |
g_clear_pointer (&key_file, (GDestroyNotify) g_key_file_unref);
|
|
Packit |
79f644 |
g_object_unref (data->daemon);
|
|
Packit |
79f644 |
g_object_unref (data->manager);
|
|
Packit |
79f644 |
g_object_unref (data->invocation);
|
|
Packit |
79f644 |
g_free (data->provider_type);
|
|
Packit |
79f644 |
g_free (data->identity);
|
|
Packit |
79f644 |
g_free (data->presentation_identity);
|
|
Packit |
79f644 |
g_variant_unref (data->credentials);
|
|
Packit |
79f644 |
g_variant_unref (data->details);
|
|
Packit |
79f644 |
g_slice_free (AddAccountData, data);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean
|
|
Packit |
79f644 |
on_manager_handle_add_account (GoaManager *manager,
|
|
Packit |
79f644 |
GDBusMethodInvocation *invocation,
|
|
Packit |
79f644 |
const gchar *provider_type,
|
|
Packit |
79f644 |
const gchar *identity,
|
|
Packit |
79f644 |
const gchar *presentation_identity,
|
|
Packit |
79f644 |
GVariant *credentials,
|
|
Packit |
79f644 |
GVariant *details,
|
|
Packit |
79f644 |
gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaDaemon *self = GOA_DAEMON (user_data);
|
|
Packit |
79f644 |
AddAccountData *data;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
data = g_slice_new0 (AddAccountData);
|
|
Packit |
79f644 |
data->daemon = g_object_ref (self);
|
|
Packit |
79f644 |
data->manager = g_object_ref (manager);
|
|
Packit |
79f644 |
data->invocation = g_object_ref (invocation);
|
|
Packit |
79f644 |
data->provider_type = g_strdup (provider_type);
|
|
Packit |
79f644 |
data->identity = g_strdup (identity);
|
|
Packit |
79f644 |
data->presentation_identity = g_strdup (presentation_identity);
|
|
Packit |
79f644 |
data->credentials = g_variant_ref (credentials);
|
|
Packit |
79f644 |
data->details = g_variant_ref (details);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
goa_provider_get_all (get_all_providers_cb, data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
return TRUE; /* invocation was handled */
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
typedef struct
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaObject *object;
|
|
Packit |
79f644 |
GList *invocations;
|
|
Packit |
79f644 |
} ObjectInvocationData;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static ObjectInvocationData *
|
|
Packit |
79f644 |
object_invocation_data_new (GoaObject *object,
|
|
Packit |
79f644 |
GDBusMethodInvocation *invocation)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
ObjectInvocationData *data;
|
|
Packit |
79f644 |
data = g_slice_new0 (ObjectInvocationData);
|
|
Packit |
79f644 |
data->object = g_object_ref (object);
|
|
Packit |
79f644 |
data->invocations = g_list_prepend (data->invocations, invocation);
|
|
Packit |
79f644 |
return data;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
object_invocation_data_unref (ObjectInvocationData *data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_list_free (data->invocations);
|
|
Packit |
79f644 |
g_object_unref (data->object);
|
|
Packit |
79f644 |
g_slice_free (ObjectInvocationData, data);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
remove_account_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GTask *task = G_TASK (user_data);
|
|
Packit |
79f644 |
GoaDaemon *self;
|
|
Packit |
79f644 |
GDBusMethodInvocation *invocation;
|
|
Packit |
79f644 |
GError *error;
|
|
Packit |
79f644 |
GoaAccount *account;
|
|
Packit |
79f644 |
GoaProvider *provider = GOA_PROVIDER (source_object);
|
|
Packit |
79f644 |
ObjectInvocationData *data;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
self = GOA_DAEMON (g_task_get_source_object (task));
|
|
Packit |
79f644 |
data = g_task_get_task_data (task);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error= NULL;
|
|
Packit |
79f644 |
if (!goa_provider_remove_account_finish (provider, res, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_warning ("goa_provider_remove_account() failed: %s (%s, %d)",
|
|
Packit |
79f644 |
error->message,
|
|
Packit |
79f644 |
g_quark_to_string (error->domain),
|
|
Packit |
79f644 |
error->code);
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
goa_daemon_reload_configuration (self);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
account = goa_object_peek_account (data->object);
|
|
Packit |
79f644 |
invocation = G_DBUS_METHOD_INVOCATION (data->invocations->data);
|
|
Packit |
79f644 |
goa_account_complete_remove (account, invocation);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_object_unref (task);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean
|
|
Packit |
79f644 |
on_account_handle_remove (GoaAccount *account,
|
|
Packit |
79f644 |
GDBusMethodInvocation *invocation,
|
|
Packit |
79f644 |
gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaDaemon *self = GOA_DAEMON (user_data);
|
|
Packit |
79f644 |
GoaObject *object;
|
|
Packit |
79f644 |
GoaProvider *provider = NULL;
|
|
Packit |
79f644 |
GKeyFile *key_file = NULL;
|
|
Packit |
79f644 |
GTask *task = NULL;
|
|
Packit |
79f644 |
ObjectInvocationData *data;
|
|
Packit |
79f644 |
const gchar *provider_type = NULL;
|
|
Packit |
79f644 |
gchar *group = NULL;
|
|
Packit |
79f644 |
GError *error;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (goa_account_get_is_locked (account))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
g_set_error_literal (&error,
|
|
Packit |
79f644 |
GOA_ERROR,
|
|
Packit |
79f644 |
GOA_ERROR_NOT_SUPPORTED,
|
|
Packit |
79f644 |
_("IsLocked property is set for account"));
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* update key-file - right now we only support removing the account
|
|
Packit |
79f644 |
* if the entry is in ~/.config/goa-1.0/accounts.conf
|
|
Packit |
79f644 |
*/
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
key_file = g_key_file_new ();
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!g_key_file_load_from_file (key_file,
|
|
Packit |
79f644 |
self->home_conf_file_path,
|
|
Packit |
79f644 |
G_KEY_FILE_KEEP_COMMENTS,
|
|
Packit |
79f644 |
&error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
group = g_strdup_printf ("Account %s", goa_account_get_id (account));
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!g_key_file_remove_group (key_file, group, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!g_key_file_save_to_file (key_file, self->home_conf_file_path, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_prefix_error (&error, "Error writing key-value-file %s: ", self->home_conf_file_path);
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
provider_type = goa_account_get_provider_type (account);
|
|
Packit |
79f644 |
if (provider_type == NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
g_set_error_literal (&error,
|
|
Packit |
79f644 |
GOA_ERROR,
|
|
Packit |
79f644 |
GOA_ERROR_FAILED, /* TODO: more specific */
|
|
Packit |
79f644 |
_("ProviderType property is not set for account"));
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
provider = goa_provider_get_for_provider_type (provider_type);
|
|
Packit |
79f644 |
if (provider == NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
g_set_error (&error,
|
|
Packit |
79f644 |
GOA_ERROR,
|
|
Packit |
79f644 |
GOA_ERROR_FAILED, /* TODO: more specific */
|
|
Packit |
79f644 |
_("Failed to find a provider for: %s"),
|
|
Packit |
79f644 |
provider_type);
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error = NULL;
|
|
Packit |
79f644 |
if (!goa_utils_delete_credentials_for_account_sync (provider, account, NULL, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_dbus_method_invocation_take_error (invocation, error);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
object = GOA_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (account)));
|
|
Packit |
79f644 |
data = object_invocation_data_new (object, invocation);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
task = g_task_new (self, NULL, NULL, NULL);
|
|
Packit |
79f644 |
g_task_set_task_data (task, data, (GDestroyNotify) object_invocation_data_unref);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
goa_provider_remove_account (provider, object, NULL, remove_account_cb, g_object_ref (task));
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
out:
|
|
Packit |
79f644 |
g_clear_object (&provider);
|
|
Packit |
79f644 |
g_clear_object (&task);
|
|
Packit |
79f644 |
g_clear_pointer (&key_file, (GDestroyNotify) g_key_file_unref);
|
|
Packit |
79f644 |
g_free (group);
|
|
Packit |
79f644 |
return TRUE; /* invocation was handled */
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean
|
|
Packit |
79f644 |
is_authorization_error (GError *error)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
gboolean ret;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_return_val_if_fail (error != NULL, FALSE);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
ret = FALSE;
|
|
Packit |
79f644 |
if (error->domain == REST_PROXY_ERROR || error->domain == SOUP_HTTP_ERROR)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
if (SOUP_STATUS_IS_CLIENT_ERROR (error->code))
|
|
Packit |
79f644 |
ret = TRUE;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else if (error->domain == GOA_ERROR)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
if (error->code == GOA_ERROR_NOT_AUTHORIZED)
|
|
Packit |
79f644 |
ret = TRUE;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
return ret;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
ensure_credentials_queue_complete (GList *invocations, GoaAccount *account, gint expires_in, GError *error)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GList *l;
|
|
Packit |
79f644 |
const gchar *id;
|
|
Packit |
79f644 |
const gchar *provider_type;
|
|
Packit |
79f644 |
gint64 timestamp;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
for (l = invocations; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (l->data);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (invocation == NULL)
|
|
Packit |
79f644 |
continue;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (error == NULL)
|
|
Packit |
79f644 |
goa_account_complete_ensure_credentials (account, invocation, expires_in);
|
|
Packit |
79f644 |
else
|
|
Packit |
79f644 |
g_dbus_method_invocation_return_gerror (invocation, error);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
id = goa_account_get_id (account);
|
|
Packit |
79f644 |
provider_type = goa_account_get_provider_type (account);
|
|
Packit |
79f644 |
timestamp = g_get_monotonic_time ();
|
|
Packit |
79f644 |
g_debug ("%" G_GINT64_FORMAT ": Handled EnsureCredentials (%s, %s)", timestamp, provider_type, id);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
ensure_credentials_queue_collector (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GTask *task = G_TASK (user_data);
|
|
Packit |
79f644 |
GTask *task_queued;
|
|
Packit |
79f644 |
GoaDaemon *self;
|
|
Packit |
79f644 |
GoaAccount *account;
|
|
Packit |
79f644 |
GoaProvider *provider = GOA_PROVIDER (source_object);
|
|
Packit |
79f644 |
GError *error;
|
|
Packit |
79f644 |
ObjectInvocationData *data;
|
|
Packit |
79f644 |
gint expires_in;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
self = GOA_DAEMON (g_task_get_source_object (task));
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
task_queued = G_TASK (g_queue_pop_head (self->ensure_credentials_queue));
|
|
Packit |
79f644 |
g_assert (task == task_queued);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
data = g_task_get_task_data (task);
|
|
Packit |
79f644 |
account = goa_object_peek_account (data->object);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
error= NULL;
|
|
Packit |
79f644 |
if (!goa_provider_ensure_credentials_finish (provider, &expires_in, res, &error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
/* Set AttentionNeeded only if the error is an authorization error */
|
|
Packit |
79f644 |
if (is_authorization_error (error))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
if (!goa_account_get_attention_needed (account))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
goa_account_set_attention_needed (account, TRUE);
|
|
Packit |
79f644 |
g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (account));
|
|
Packit |
79f644 |
g_message ("%s: Setting AttentionNeeded to TRUE because EnsureCredentials() failed with: %s (%s, %d)",
|
|
Packit |
79f644 |
g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object)),
|
|
Packit |
79f644 |
error->message, g_quark_to_string (error->domain), error->code);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
ensure_credentials_queue_complete (data->invocations, account, 0, error);
|
|
Packit |
79f644 |
g_error_free (error);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
else
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
/* Clear AttentionNeeded flag if set */
|
|
Packit |
79f644 |
if (goa_account_get_attention_needed (account))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
goa_account_set_attention_needed (account, FALSE);
|
|
Packit |
79f644 |
g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (account));
|
|
Packit |
79f644 |
g_message ("%s: Setting AttentionNeeded to FALSE because EnsureCredentials() succeded\n",
|
|
Packit |
79f644 |
g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object)));
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
ensure_credentials_queue_complete (data->invocations, account, expires_in, NULL);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
self->ensure_credentials_running = FALSE;
|
|
Packit |
79f644 |
ensure_credentials_queue_check (self);
|
|
Packit |
79f644 |
g_object_unref (task);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gint
|
|
Packit |
79f644 |
ensure_credentials_queue_sort (gconstpointer a, gconstpointer b, gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GTask *task_a = G_TASK (a);
|
|
Packit |
79f644 |
GTask *task_b = G_TASK (b);
|
|
Packit |
79f644 |
gint priority_a;
|
|
Packit |
79f644 |
gint priority_b;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
priority_a = g_task_get_priority (task_a);
|
|
Packit |
79f644 |
priority_b = g_task_get_priority (task_b);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
return priority_a - priority_b;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
ensure_credentials_queue_check (GoaDaemon *self)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaAccount *account;
|
|
Packit |
79f644 |
GoaProvider *provider = NULL;
|
|
Packit |
79f644 |
GTask *task;
|
|
Packit |
79f644 |
ObjectInvocationData *data;
|
|
Packit |
79f644 |
const gchar *id;
|
|
Packit |
79f644 |
const gchar *provider_type;
|
|
Packit |
79f644 |
gint64 timestamp;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (self->ensure_credentials_running)
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (self->ensure_credentials_queue->length == 0)
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
g_queue_sort (self->ensure_credentials_queue, ensure_credentials_queue_sort, NULL);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
task = G_TASK (g_queue_peek_head (self->ensure_credentials_queue));
|
|
Packit |
79f644 |
self->ensure_credentials_running = TRUE;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
data = (ObjectInvocationData *) g_task_get_task_data (task);
|
|
Packit |
79f644 |
account = goa_object_peek_account (data->object);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
id = goa_account_get_id (account);
|
|
Packit |
79f644 |
provider_type = goa_account_get_provider_type (account);
|
|
Packit |
79f644 |
timestamp = g_get_monotonic_time ();
|
|
Packit |
79f644 |
g_debug ("%" G_GINT64_FORMAT ": Handling EnsureCredentials (%s, %s)", timestamp, provider_type, id);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
provider = goa_provider_get_for_provider_type (provider_type);
|
|
Packit |
79f644 |
g_assert_nonnull (provider);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
goa_provider_ensure_credentials (provider,
|
|
Packit |
79f644 |
data->object,
|
|
Packit |
79f644 |
NULL, /* GCancellable */
|
|
Packit |
79f644 |
ensure_credentials_queue_collector,
|
|
Packit |
79f644 |
task);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
out:
|
|
Packit |
79f644 |
g_clear_object (&provider);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean
|
|
Packit |
79f644 |
ensure_credentials_queue_coalesce (GoaDaemon *self, GoaObject *object, GDBusMethodInvocation *invocation)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GList *l;
|
|
Packit |
79f644 |
GoaAccount *account;
|
|
Packit |
79f644 |
const gchar *id;
|
|
Packit |
79f644 |
gboolean ret = FALSE;
|
|
Packit |
79f644 |
gint priority;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
account = goa_object_peek_account (object);
|
|
Packit |
79f644 |
id = goa_account_get_id (account);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
priority = (invocation == NULL) ? G_PRIORITY_LOW : G_PRIORITY_HIGH;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
for (l = self->ensure_credentials_queue->head; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaAccount *account_queued;
|
|
Packit |
79f644 |
GTask *task = G_TASK (l->data);
|
|
Packit |
79f644 |
ObjectInvocationData *data;
|
|
Packit |
79f644 |
const gchar *id_queued;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
data = g_task_get_task_data (task);
|
|
Packit |
79f644 |
account_queued = goa_object_peek_account (data->object);
|
|
Packit |
79f644 |
id_queued = goa_account_get_id (account_queued);
|
|
Packit |
79f644 |
if (g_strcmp0 (id, id_queued) == 0)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
gint priority_queued;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
priority_queued = g_task_get_priority (task);
|
|
Packit |
79f644 |
if (priority < priority_queued)
|
|
Packit |
79f644 |
g_task_set_priority (task, priority);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
data->invocations = g_list_prepend (data->invocations, invocation);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
ret = TRUE;
|
|
Packit |
79f644 |
break;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
return ret;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
static gboolean
|
|
Packit |
79f644 |
on_account_handle_ensure_credentials (GoaAccount *account,
|
|
Packit |
79f644 |
GDBusMethodInvocation *invocation,
|
|
Packit |
79f644 |
gpointer user_data)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaDaemon *self = GOA_DAEMON (user_data);
|
|
Packit |
79f644 |
GoaObject *object;
|
|
Packit |
79f644 |
GoaProvider *provider = NULL;
|
|
Packit |
79f644 |
GTask *task = NULL;
|
|
Packit |
79f644 |
ObjectInvocationData *data;
|
|
Packit |
79f644 |
const gchar *id;
|
|
Packit |
79f644 |
const gchar *method_name;
|
|
Packit |
79f644 |
const gchar *provider_type;
|
|
Packit |
79f644 |
gint64 timestamp;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
id = goa_account_get_id (account);
|
|
Packit |
79f644 |
provider_type = goa_account_get_provider_type (account);
|
|
Packit |
79f644 |
method_name = g_dbus_method_invocation_get_method_name (invocation);
|
|
Packit |
79f644 |
timestamp = g_get_monotonic_time ();
|
|
Packit |
79f644 |
g_debug ("%" G_GINT64_FORMAT ": Received %s (%s, %s)", timestamp, method_name, provider_type, id);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
provider = goa_provider_get_for_provider_type (provider_type);
|
|
Packit |
79f644 |
if (provider == NULL)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
g_dbus_method_invocation_return_error (invocation,
|
|
Packit |
79f644 |
GOA_ERROR,
|
|
Packit |
79f644 |
GOA_ERROR_FAILED,
|
|
Packit |
79f644 |
"Unsupported account type %s for id %s (no provider)",
|
|
Packit |
79f644 |
provider_type,
|
|
Packit |
79f644 |
id);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
object = GOA_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (account)));
|
|
Packit |
79f644 |
if (ensure_credentials_queue_coalesce (self, object, invocation))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
timestamp = g_get_monotonic_time ();
|
|
Packit |
79f644 |
g_debug ("%" G_GINT64_FORMAT ": Coalesced %s (%s, %s)",
|
|
Packit |
79f644 |
timestamp,
|
|
Packit |
79f644 |
method_name,
|
|
Packit |
79f644 |
provider_type,
|
|
Packit |
79f644 |
id);
|
|
Packit |
79f644 |
goto out;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
data = object_invocation_data_new (object, invocation);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
task = g_task_new (self, NULL, NULL, NULL);
|
|
Packit |
79f644 |
g_task_set_priority (task, G_PRIORITY_HIGH);
|
|
Packit |
79f644 |
g_task_set_task_data (task, data, (GDestroyNotify) object_invocation_data_unref);
|
|
Packit |
79f644 |
g_queue_push_tail (self->ensure_credentials_queue, g_object_ref (task));
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
ensure_credentials_queue_check (self);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
out:
|
|
Packit |
79f644 |
g_clear_object (&provider);
|
|
Packit |
79f644 |
g_clear_object (&task);
|
|
Packit |
79f644 |
return TRUE; /* invocation was handled */
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
/* <internal>
|
|
Packit |
79f644 |
* goa_daemon_check_credentials:
|
|
Packit |
79f644 |
* @self: A #GoaDaemon
|
|
Packit |
79f644 |
*
|
|
Packit |
79f644 |
* Checks whether credentials are valid and tries to refresh them if
|
|
Packit |
79f644 |
* not. It also reports whether accounts are usable with the current
|
|
Packit |
79f644 |
* network.
|
|
Packit |
79f644 |
*/
|
|
Packit |
79f644 |
static void
|
|
Packit |
79f644 |
goa_daemon_check_credentials (GoaDaemon *self)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GList *l;
|
|
Packit |
79f644 |
GList *objects;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self->object_manager));
|
|
Packit |
79f644 |
for (l = objects; l != NULL; l = l->next)
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
GoaAccount *account;
|
|
Packit |
79f644 |
GoaObject *object = GOA_OBJECT (l->data);
|
|
Packit |
79f644 |
GoaProvider *provider = NULL;
|
|
Packit |
79f644 |
GTask *task = NULL;
|
|
Packit |
79f644 |
ObjectInvocationData *data;
|
|
Packit |
79f644 |
const gchar *id;
|
|
Packit |
79f644 |
const gchar *provider_type;
|
|
Packit |
79f644 |
gint64 timestamp;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
account = goa_object_peek_account (object);
|
|
Packit |
79f644 |
if (account == NULL)
|
|
Packit |
79f644 |
goto cleanup_and_continue;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
provider_type = goa_account_get_provider_type (account);
|
|
Packit |
79f644 |
provider = goa_provider_get_for_provider_type (provider_type);
|
|
Packit |
79f644 |
if (provider == NULL)
|
|
Packit |
79f644 |
goto cleanup_and_continue;
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
id = goa_account_get_id (account);
|
|
Packit |
79f644 |
provider_type = goa_account_get_provider_type (account);
|
|
Packit |
79f644 |
timestamp = g_get_monotonic_time ();
|
|
Packit |
79f644 |
g_debug ("%" G_GINT64_FORMAT ": Calling EnsureCredentials (%s, %s)",
|
|
Packit |
79f644 |
timestamp,
|
|
Packit |
79f644 |
provider_type,
|
|
Packit |
79f644 |
id);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
if (ensure_credentials_queue_coalesce (self, object, NULL))
|
|
Packit |
79f644 |
{
|
|
Packit |
79f644 |
timestamp = g_get_monotonic_time ();
|
|
Packit |
79f644 |
g_debug ("%" G_GINT64_FORMAT ": Coalesced EnsureCredentials (%s, %s)",
|
|
Packit |
79f644 |
timestamp,
|
|
Packit |
79f644 |
provider_type,
|
|
Packit |
79f644 |
id);
|
|
Packit |
79f644 |
goto cleanup_and_continue;
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
data = object_invocation_data_new (object, NULL);
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
task = g_task_new (self, NULL, NULL, NULL);
|
|
Packit |
79f644 |
g_task_set_priority (task, G_PRIORITY_LOW);
|
|
Packit |
79f644 |
g_task_set_task_data (task, data, (GDestroyNotify) object_invocation_data_unref);
|
|
Packit |
79f644 |
g_queue_push_tail (self->ensure_credentials_queue, g_object_ref (task));
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
cleanup_and_continue:
|
|
Packit |
79f644 |
g_clear_object (&provider);
|
|
Packit |
79f644 |
g_clear_object (&task);
|
|
Packit |
79f644 |
}
|
|
Packit |
79f644 |
|
|
Packit |
79f644 |
ensure_credentials_queue_check (self);
|
|
Packit |
79f644 |
g_list_free_full (objects, g_object_unref);
|
|
Packit |
79f644 |
}
|