Blame src/goabackend/goaprovider.c

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 <glib/gi18n-lib.h>
Packit 79f644
Packit 79f644
#include "goaprovider.h"
Packit 79f644
#include "goaprovider-priv.h"
Packit 79f644
#include "goaproviderfactory.h"
Packit 79f644
#include "goaexchangeprovider.h"
Packit 79f644
#include "goagoogleprovider.h"
Packit 79f644
#include "goafacebookprovider.h"
Packit 79f644
#include "goaimapsmtpprovider.h"
Packit 79f644
#include "goaowncloudprovider.h"
Packit 79f644
#include "goaflickrprovider.h"
Packit 79f644
#include "goafoursquareprovider.h"
Packit 79f644
#include "goawindowsliveprovider.h"
Packit 79f644
#include "goatelepathyfactory.h"
Packit 79f644
#include "goapocketprovider.h"
Packit 79f644
#include "goamediaserverprovider.h"
Packit 79f644
#include "goalastfmprovider.h"
Packit 79f644
#include "goatodoistprovider.h"
Packit 79f644
Packit 79f644
#ifdef GOA_KERBEROS_ENABLED
Packit 79f644
#include "goakerberosprovider.h"
Packit 79f644
#endif
Packit 79f644
Packit 79f644
#include "goautils.h"
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * SECTION:goaprovider
Packit 79f644
 * @title: GoaProvider
Packit 79f644
 * @short_description: Abstract base class for providers
Packit 79f644
 *
Packit 79f644
 * #GoaProvider is the base type for all providers.
Packit 79f644
 */
Packit 79f644
Packit 79f644
enum {
Packit 79f644
  PROP_0,
Packit 79f644
  PROP_PRESEED_DATA,
Packit 79f644
  NUM_PROPERTIES
Packit 79f644
};
Packit 79f644
Packit 79f644
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
Packit 79f644
Packit 79f644
static gboolean goa_provider_ensure_credentials_sync_real (GoaProvider   *self,
Packit 79f644
                                                           GoaObject     *object,
Packit 79f644
                                                           gint          *out_expires_in,
Packit 79f644
                                                           GCancellable  *cancellable,
Packit 79f644
                                                           GError       **error);
Packit 79f644
Packit 79f644
static gboolean goa_provider_build_object_real (GoaProvider         *self,
Packit 79f644
                                                GoaObjectSkeleton   *object,
Packit 79f644
                                                GKeyFile            *key_file,
Packit 79f644
                                                const gchar         *group,
Packit 79f644
                                                GDBusConnection     *connection,
Packit 79f644
                                                gboolean             just_added,
Packit 79f644
                                                GError             **error);
Packit 79f644
Packit 79f644
static guint goa_provider_get_credentials_generation_real (GoaProvider *self);
Packit 79f644
Packit 79f644
static GIcon *goa_provider_get_provider_icon_real (GoaProvider *self,
Packit 79f644
                                                   GoaObject   *object);
Packit 79f644
Packit 79f644
static void goa_provider_initialize_real (GoaProvider *self);
Packit 79f644
Packit 79f644
static void goa_provider_remove_account_real (GoaProvider          *self,
Packit 79f644
                                              GoaObject            *object,
Packit 79f644
                                              GCancellable         *cancellable,
Packit 79f644
                                              GAsyncReadyCallback   callback,
Packit 79f644
                                              gpointer              user_data);
Packit 79f644
Packit 79f644
static gboolean goa_provider_remove_account_finish_real (GoaProvider   *self,
Packit 79f644
                                                         GAsyncResult  *res,
Packit 79f644
                                                         GError       **error);
Packit 79f644
Packit 79f644
static void goa_provider_show_account_real (GoaProvider         *provider,
Packit 79f644
                                            GoaClient           *client,
Packit 79f644
                                            GoaObject           *object,
Packit 79f644
                                            GtkBox              *vbox,
Packit 79f644
                                            GtkGrid             *dummy1,
Packit 79f644
                                            GtkGrid             *dummy2);
Packit 79f644
Packit 79f644
G_DEFINE_ABSTRACT_TYPE (GoaProvider, goa_provider, G_TYPE_OBJECT);
Packit 79f644
Packit 79f644
static struct {
Packit 79f644
  GoaProviderFeatures feature;
Packit 79f644
  const gchar *property;
Packit 79f644
  const gchar *blurb;
Packit 79f644
} provider_features_info[] = {
Packit 79f644
  /* The order in which the features are listed is
Packit 79f644
   * important because it affects the order in which they are
Packit 79f644
   * displayed in the show_account() UI
Packit 79f644
   */
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_MAIL,
Packit 79f644
    .property = "mail-disabled",
Packit 79f644
    .blurb = N_("_Mail"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_CALENDAR,
Packit 79f644
    .property = "calendar-disabled",
Packit 79f644
    .blurb = N_("Cale_ndar"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_CONTACTS,
Packit 79f644
    .property = "contacts-disabled",
Packit 79f644
    .blurb = N_("_Contacts"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_CHAT,
Packit 79f644
    .property = "chat-disabled",
Packit 79f644
    .blurb = N_("C_hat"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_DOCUMENTS,
Packit 79f644
    .property = "documents-disabled",
Packit 79f644
    .blurb = N_("_Documents"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_MUSIC,
Packit 79f644
    .property = "music-disabled",
Packit 79f644
    .blurb = N_("M_usic"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_PHOTOS,
Packit 79f644
    .property = "photos-disabled",
Packit 79f644
    .blurb = N_("_Photos"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_FILES,
Packit 79f644
    .property = "files-disabled",
Packit 79f644
    .blurb = N_("_Files"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_TICKETING,
Packit 79f644
    .property = "ticketing-disabled",
Packit 79f644
    .blurb = N_("Network _Resources"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_READ_LATER,
Packit 79f644
    .property = "read-later-disabled",
Packit 79f644
    .blurb = N_("_Read Later"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_PRINTERS,
Packit 79f644
    .property = "printers-disabled",
Packit 79f644
    .blurb = N_("Prin_ters"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_MAPS,
Packit 79f644
    .property = "maps-disabled",
Packit 79f644
    .blurb = N_("_Maps"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_TODO,
Packit 79f644
    .property = "todo-disabled",
Packit 79f644
    .blurb = N_("T_o Do"),
Packit 79f644
  },
Packit 79f644
  {
Packit 79f644
    .feature = GOA_PROVIDER_FEATURE_INVALID,
Packit 79f644
    .property = NULL,
Packit 79f644
    .blurb = NULL,
Packit 79f644
  }
Packit 79f644
};
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_provider_get_property (GObject *object,
Packit 79f644
                           guint property_id,
Packit 79f644
                           GValue *value,
Packit 79f644
                           GParamSpec *pspec)
Packit 79f644
{
Packit 79f644
    switch (property_id) {
Packit 79f644
    case PROP_PRESEED_DATA:
Packit 79f644
        g_value_set_variant (value, NULL);
Packit 79f644
        break;
Packit 79f644
    default:
Packit 79f644
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit 79f644
        break;
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_provider_set_property (GObject *object,
Packit 79f644
                           guint property_id,
Packit 79f644
                           const GValue *value,
Packit 79f644
                           GParamSpec *pspec)
Packit 79f644
{
Packit 79f644
    switch (property_id) {
Packit 79f644
    case PROP_PRESEED_DATA:
Packit 79f644
        break;
Packit 79f644
    default:
Packit 79f644
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit 79f644
        break;
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_provider_init (GoaProvider *self)
Packit 79f644
{
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_provider_class_init (GoaProviderClass *klass)
Packit 79f644
{
Packit 79f644
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
Packit 79f644
Packit 79f644
  object_class->set_property = goa_provider_set_property;
Packit 79f644
  object_class->get_property = goa_provider_get_property;
Packit 79f644
Packit 79f644
  klass->build_object = goa_provider_build_object_real;
Packit 79f644
  klass->ensure_credentials_sync = goa_provider_ensure_credentials_sync_real;
Packit 79f644
  klass->get_credentials_generation = goa_provider_get_credentials_generation_real;
Packit 79f644
  klass->get_provider_icon = goa_provider_get_provider_icon_real;
Packit 79f644
  klass->initialize = goa_provider_initialize_real;
Packit 79f644
  klass->remove_account = goa_provider_remove_account_real;
Packit 79f644
  klass->remove_account_finish = goa_provider_remove_account_finish_real;
Packit 79f644
  klass->show_account = goa_provider_show_account_real;
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * GoaProvider:preseed-data
Packit 79f644
 *
Packit 79f644
 * An #GVariant of type a{sv} storing any information already collected that
Packit 79f644
 * can be useful when creating a new account. For instance, this can be useful
Packit 79f644
 * to reuse the HTTP cookies from an existing browser session to skip the
Packit 79f644
 * prompt for username and password in the OAuth2-based providers by passing
Packit 79f644
 * a #GVariant with the following contents:
Packit 79f644
 *
Packit 79f644
 * <informalexample>
Packit 79f644
 * <programlisting>
Packit 79f644
 * {
Packit 79f644
 *   "cookies": [
Packit 79f644
 *     {
Packit 79f644
 *       "domain": "example.com",
Packit 79f644
 *       "name": "LSID",
Packit 79f644
 *       "value": "asdfasdfasdf"
Packit 79f644
 *     },
Packit 79f644
 *     {
Packit 79f644
 *       "domain": "accounts.example.com",
Packit 79f644
 *       "name": "SSID",
Packit 79f644
 *       "value": "asdfasdfasdf"
Packit 79f644
 *     }
Packit 79f644
 *   ]
Packit 79f644
 * }
Packit 79f644
 * </programlisting>
Packit 79f644
 * </informalexample>
Packit 79f644
 *
Packit 79f644
 * Unknown or unsupported keys will be ignored by providers.
Packit 79f644
 *
Packit 79f644
 * Deprecated: 3.28: This property does nothing.
Packit 79f644
 */
Packit 79f644
  properties[PROP_PRESEED_DATA] =
Packit 79f644
    g_param_spec_variant ("preseed-data",
Packit 79f644
        "Collected data to pre-seed account creation",
Packit 79f644
        "A a{sv} #GVariant containing a provider-type specific set of data that"
Packit 79f644
        "can be useful during account creation (eg. http cookies from an existing"
Packit 79f644
        "browser session or the entrypoint url for self-hosted services).",
Packit 79f644
        G_VARIANT_TYPE_VARDICT,
Packit 79f644
        NULL,
Packit 79f644
        G_PARAM_DEPRECATED | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
Packit 79f644
Packit 79f644
  g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
Packit 79f644
}
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_get_provider_type:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 *
Packit 79f644
 * Gets the type of @self.
Packit 79f644
 *
Packit 79f644
 * This is a pure virtual method - a subclass must provide an
Packit 79f644
 * implementation.
Packit 79f644
 *
Packit 79f644
 * Returns: (transfer none): A string owned by @self, do not free.
Packit 79f644
 */
Packit 79f644
const gchar *
Packit 79f644
goa_provider_get_provider_type (GoaProvider *self)
Packit 79f644
{
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), NULL);
Packit 79f644
  return GOA_PROVIDER_GET_CLASS (self)->get_provider_type (self);
Packit 79f644
}
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_get_provider_name:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 * @object: (allow-none): A #GoaObject for an account.
Packit 79f644
 *
Packit 79f644
 * Gets a name for @self and @object that is suitable for display
Packit 79f644
 * in an user interface. The returned value may depend on @object (if
Packit 79f644
 * it's not %NULL) - for example, hosted accounts might return a
Packit 79f644
 * different name.
Packit 79f644
 *
Packit 79f644
 * This is a pure virtual method - a subclass must provide an
Packit 79f644
 * implementation.
Packit 79f644
 *
Packit 79f644
 * Returns: (transfer full): A string that should be freed with g_free().
Packit 79f644
 */
Packit 79f644
gchar *
Packit 79f644
goa_provider_get_provider_name (GoaProvider *self,
Packit 79f644
                                GoaObject   *object)
Packit 79f644
{
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), NULL);
Packit 79f644
  return GOA_PROVIDER_GET_CLASS (self)->get_provider_name (self, object);
Packit 79f644
}
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_get_provider_icon:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 * @object: A #GoaObject for an account.
Packit 79f644
 *
Packit 79f644
 * Gets an icon for @self and @object that is suitable for display
Packit 79f644
 * in an user interface. The returned value may depend on @object -
Packit 79f644
 * for example, hosted accounts might return a different icon.
Packit 79f644
 *
Packit 79f644
 * This is a virtual method with a default implementation that returns
Packit 79f644
 * a #GThemedIcon with fallbacks constructed from the name
Packit 79f644
 * <literal>goa-account-TYPE</literal> where <literal>TYPE</literal>
Packit 79f644
 * is the return value of goa_provider_get_provider_type().
Packit 79f644
 *
Packit 79f644
 * Returns: (transfer full): An icon that should be freed with g_object_unref().
Packit 79f644
 */
Packit 79f644
GIcon *
Packit 79f644
goa_provider_get_provider_icon (GoaProvider *self,
Packit 79f644
                                GoaObject   *object)
Packit 79f644
{
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), NULL);
Packit 79f644
  return GOA_PROVIDER_GET_CLASS (self)->get_provider_icon (self, object);
Packit 79f644
}
Packit 79f644
Packit 79f644
static GIcon *
Packit 79f644
goa_provider_get_provider_icon_real (GoaProvider *self,
Packit 79f644
                                     GoaObject   *object)
Packit 79f644
{
Packit 79f644
  GIcon *ret;
Packit 79f644
  gchar *s;
Packit 79f644
  s = g_strdup_printf ("goa-account-%s", goa_provider_get_provider_type (self));
Packit 79f644
  ret = g_themed_icon_new_with_default_fallbacks (s);
Packit 79f644
  g_free (s);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_get_provider_group:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 *
Packit 79f644
 * Gets the group to which @self belongs that is suitable for
Packit 79f644
 * organizing the providers while displaying them in an user
Packit 79f644
 * interface.
Packit 79f644
 *
Packit 79f644
 * This is a pure virtual method - a subclass must provide an
Packit 79f644
 * implementation.
Packit 79f644
 *
Packit 79f644
 * Returns: A #GoaProviderGroup.
Packit 79f644
 *
Packit 79f644
 * Since: 3.8
Packit 79f644
 *
Packit 79f644
 * Deprecated: 3.10: Use goa_provider_get_provider_features() instead.
Packit 79f644
 */
Packit 79f644
GoaProviderGroup
Packit 79f644
goa_provider_get_provider_group (GoaProvider *self)
Packit 79f644
{
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), GOA_PROVIDER_GROUP_INVALID);
Packit 79f644
  return GOA_PROVIDER_GET_CLASS (self)->get_provider_group (self);
Packit 79f644
}
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_get_provider_features:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 *
Packit 79f644
 * Get the features bitmask (eg. %GOA_PROVIDER_FEATURE_CHAT|%GOA_PROVIDER_FEATURE_CONTACTS)
Packit 79f644
 * supported by the provider.
Packit 79f644
 *
Packit 79f644
 * Returns: The #GoaProviderFeatures bitmask with the provided features.
Packit 79f644
 *
Packit 79f644
 * Since: 3.10
Packit 79f644
 */
Packit 79f644
GoaProviderFeatures
Packit 79f644
goa_provider_get_provider_features (GoaProvider *self)
Packit 79f644
{
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), GOA_PROVIDER_FEATURE_INVALID);
Packit 79f644
  g_return_val_if_fail (GOA_PROVIDER_GET_CLASS (self)->get_provider_features != NULL, GOA_PROVIDER_FEATURE_INVALID);
Packit 79f644
  return GOA_PROVIDER_GET_CLASS (self)->get_provider_features (self);
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
void
Packit 79f644
goa_provider_initialize (GoaProvider *self)
Packit 79f644
{
Packit 79f644
  g_return_if_fail (GOA_IS_PROVIDER (self));
Packit 79f644
Packit 79f644
  GOA_PROVIDER_GET_CLASS (self)->initialize (self);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_provider_initialize_real (GoaProvider *self)
Packit 79f644
{
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_add_account:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 * @client: A #GoaClient.
Packit 79f644
 * @dialog: A #GtkDialog.
Packit 79f644
 * @vbox: A vertically oriented #GtkBox to put content in.
Packit 79f644
 * @error: Return location for error or %NULL.
Packit 79f644
 *
Packit 79f644
 * This method brings up the user interface necessary to create a new
Packit 79f644
 * account on @client of the type for @self, interacts with the
Packit 79f644
 * user to get all information needed and creates the account.
Packit 79f644
 *
Packit 79f644
 * The passed in @dialog widget is guaranteed to be visible with @vbox
Packit 79f644
 * being empty and the only visible widget in @dialog's content
Packit 79f644
 * area. The dialog has exactly one action widget, a cancel button
Packit 79f644
 * with response id GTK_RESPONSE_CANCEL. Implementations are free to
Packit 79f644
 * add additional action widgets, as needed.
Packit 79f644
 *
Packit 79f644
 * If an account was successfully created, a #GoaObject for the
Packit 79f644
 * created account is returned. If @dialog is dismissed, %NULL is
Packit 79f644
 * returned and @error is set to %GOA_ERROR_DIALOG_DISMISSED. If an
Packit 79f644
 * account couldn't be created then @error is set. In some cases,
Packit 79f644
 * for example, when the credentials could not be stored in the
Packit 79f644
 * keyring, a #GoaObject can be returned even if @error is set.
Packit 79f644
 *
Packit 79f644
 * The caller will always show an error dialog if @error is set unless
Packit 79f644
 * the error is %GOA_ERROR_DIALOG_DISMISSED.
Packit 79f644
 *
Packit 79f644
 * Implementations should run the 
Packit 79f644
 * linkend="g_main_context_default">default main loop</link> while
Packit 79f644
 * interacting with the user and may do so using e.g. gtk_dialog_run()
Packit 79f644
 * on @dialog.
Packit 79f644
 *
Packit 79f644
 * This is a pure virtual method - a subclass must provide an
Packit 79f644
 * implementation.
Packit 79f644
 *
Packit 79f644
 * Returns: The #GoaObject for the created account (must be relased
Packit 79f644
 *   with g_object_unref()) or %NULL if @error is set.
Packit 79f644
 */
Packit 79f644
GoaObject *
Packit 79f644
goa_provider_add_account (GoaProvider  *self,
Packit 79f644
                          GoaClient    *client,
Packit 79f644
                          GtkDialog    *dialog,
Packit 79f644
                          GtkBox       *vbox,
Packit 79f644
                          GError      **error)
Packit 79f644
{
Packit 79f644
  GoaObject *ret;
Packit 79f644
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), NULL);
Packit 79f644
  g_return_val_if_fail (GOA_IS_CLIENT (client), NULL);
Packit 79f644
  g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
Packit 79f644
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
Packit 79f644
Packit 79f644
  ret = GOA_PROVIDER_GET_CLASS (self)->add_account (self, client, dialog, vbox, error);
Packit 79f644
Packit 79f644
  g_warn_if_fail ((ret == NULL && (error == NULL || *error != NULL)) || GOA_IS_OBJECT (ret));
Packit 79f644
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_refresh_account:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 * @client: A #GoaClient.
Packit 79f644
 * @object: A #GoaObject with a #GoaAccount interface.
Packit 79f644
 * @parent: (allow-none): Transient parent of dialogs or %NULL.
Packit 79f644
 * @error: Return location for error or %NULL.
Packit 79f644
 *
Packit 79f644
 * This method brings up the user interface necessary for refreshing
Packit 79f644
 * the credentials for the account specified by @object. This
Packit 79f644
 * typically involves having the user log in to the account again.
Packit 79f644
 *
Packit 79f644
 * Implementations should use @parent (unless %NULL) as the transient
Packit 79f644
 * parent of any created windows/dialogs.
Packit 79f644
 *
Packit 79f644
 * Implementations should run the 
Packit 79f644
 * linkend="g_main_context_default">default main loop</link> while
Packit 79f644
 * interacting with the user.
Packit 79f644
 *
Packit 79f644
 * This is a pure virtual method - a subclass must provide an
Packit 79f644
 * implementation.
Packit 79f644
 *
Packit 79f644
 * Returns: %TRUE if the account has been refreshed, %FALSE if @error
Packit 79f644
 * is set.
Packit 79f644
 */
Packit 79f644
gboolean
Packit 79f644
goa_provider_refresh_account (GoaProvider  *self,
Packit 79f644
                              GoaClient    *client,
Packit 79f644
                              GoaObject    *object,
Packit 79f644
                              GtkWindow    *parent,
Packit 79f644
                              GError      **error)
Packit 79f644
{
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), FALSE);
Packit 79f644
  g_return_val_if_fail (GOA_IS_CLIENT (client), FALSE);
Packit 79f644
  g_return_val_if_fail (GOA_IS_OBJECT (object) && goa_object_peek_account (object) != NULL, FALSE);
Packit 79f644
  g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), FALSE);
Packit 79f644
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Packit 79f644
Packit 79f644
  return GOA_PROVIDER_GET_CLASS (self)->refresh_account (self, client, object, parent, error);
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_show_account:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 * @client: A #GoaClient.
Packit 79f644
 * @object: A #GoaObject with a #GoaAccount interface.
Packit 79f644
 * @vbox: A vertically oriented #GtkBox to put content in.
Packit 79f644
 * @grid: A #GtkGrid to put content in.
Packit 79f644
 * @dummy: Unused.
Packit 79f644
 *
Packit 79f644
 * Method used to add widgets in the control panel for the account
Packit 79f644
 * represented by @object.
Packit 79f644
 *
Packit 79f644
 * This is a virtual method where the default implementation adds
Packit 79f644
 * one GtkSwitch per service supported by the provider (as reported
Packit 79f644
 * by goa_provider_get_provider_features()).
Packit 79f644
 */
Packit 79f644
void
Packit 79f644
goa_provider_show_account (GoaProvider         *self,
Packit 79f644
                           GoaClient           *client,
Packit 79f644
                           GoaObject           *object,
Packit 79f644
                           GtkBox              *vbox,
Packit 79f644
                           GtkGrid             *dummy1,
Packit 79f644
                           GtkGrid             *dummy2)
Packit 79f644
{
Packit 79f644
  g_return_if_fail (GOA_IS_PROVIDER (self));
Packit 79f644
  g_return_if_fail (GOA_IS_CLIENT (client));
Packit 79f644
  g_return_if_fail (GOA_IS_OBJECT (object) && goa_object_peek_account (object) != NULL);
Packit 79f644
  g_return_if_fail (GTK_IS_BOX (vbox));
Packit 79f644
Packit 79f644
  GOA_PROVIDER_GET_CLASS (self)->show_account (self, client, object, vbox, dummy1, dummy2);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_provider_show_account_real (GoaProvider         *provider,
Packit 79f644
                                GoaClient           *client,
Packit 79f644
                                GoaObject           *object,
Packit 79f644
                                GtkBox              *vbox,
Packit 79f644
                                GtkGrid             *dummy1,
Packit 79f644
                                GtkGrid             *dummy2)
Packit 79f644
{
Packit 79f644
  GoaProviderFeatures features;
Packit 79f644
  GtkWidget *grid;
Packit 79f644
  gint row;
Packit 79f644
  guint i;
Packit 79f644
  const char *label;
Packit 79f644
Packit 79f644
  row = 0;
Packit 79f644
Packit 79f644
  goa_utils_account_add_attention_needed (client, object, provider, vbox);
Packit 79f644
Packit 79f644
  grid = gtk_grid_new ();
Packit 79f644
  gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
Packit 79f644
  gtk_widget_set_hexpand (grid, TRUE);
Packit 79f644
  gtk_widget_set_margin_end (grid, 72);
Packit 79f644
  gtk_widget_set_margin_start (grid, 72);
Packit 79f644
  gtk_widget_set_margin_top (grid, 24);
Packit 79f644
  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
Packit 79f644
  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
Packit 79f644
  gtk_container_add (GTK_CONTAINER (vbox), grid);
Packit 79f644
Packit 79f644
  goa_utils_account_add_header (object, GTK_GRID (grid), row++);
Packit 79f644
Packit 79f644
  features = goa_provider_get_provider_features (provider);
Packit 79f644
  /* Translators: This is a label for a series of
Packit 79f644
   * options switches. For example: “Use for Mail”. */
Packit 79f644
  label = _("Use for");
Packit 79f644
Packit 79f644
  for (i = 0; provider_features_info[i].property != NULL; i++)
Packit 79f644
    {
Packit 79f644
      if ((features & provider_features_info[i].feature) != 0)
Packit 79f644
        {
Packit 79f644
          goa_util_add_row_switch_from_keyfile_with_blurb (GTK_GRID (grid), row++, object,
Packit 79f644
                                                           label,
Packit 79f644
                                                           provider_features_info[i].property,
Packit 79f644
                                                           _(provider_features_info[i].blurb));
Packit 79f644
          label = NULL;
Packit 79f644
        }
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_build_object:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 * @object: The #GoaObjectSkeleton that is being built.
Packit 79f644
 * @key_file: The #GKeyFile with configuation data.
Packit 79f644
 * @group: The group in @key_file to get data from.
Packit 79f644
 * @connection: The #GDBusConnection used by the daemon to connect to the message bus.
Packit 79f644
 * @just_added: Whether the account was newly created or being updated.
Packit 79f644
 * @error: Return location for error or %NULL.
Packit 79f644
 *
Packit 79f644
 * This method is called when construction account #GoaObject
Packit 79f644
 * from configuration data - it basically provides a way to add
Packit 79f644
 * provider-specific information.
Packit 79f644
 *
Packit 79f644
 * The passed in @object will have a #GoaAccount interface
Packit 79f644
 * set. Implementations should validate and use data from @key_file to
Packit 79f644
 * add more interfaces to @object.
Packit 79f644
 *
Packit 79f644
 * Note that this may be called on already exported objects - for
Packit 79f644
 * example on configuration files reload.
Packit 79f644
 *
Packit 79f644
 * This is a pure virtual method - a subclass must provide an
Packit 79f644
 * implementation.
Packit 79f644
 *
Packit 79f644
 * Returns: %TRUE if data was valid, %FALSE if @error is set.
Packit 79f644
 */
Packit 79f644
gboolean
Packit 79f644
goa_provider_build_object (GoaProvider         *self,
Packit 79f644
                           GoaObjectSkeleton   *object,
Packit 79f644
                           GKeyFile            *key_file,
Packit 79f644
                           const gchar         *group,
Packit 79f644
                           GDBusConnection     *connection,
Packit 79f644
                           gboolean             just_added,
Packit 79f644
                           GError             **error)
Packit 79f644
{
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), FALSE);
Packit 79f644
  g_return_val_if_fail (GOA_IS_OBJECT_SKELETON (object) && goa_object_peek_account (GOA_OBJECT (object)) != NULL, FALSE);
Packit 79f644
  g_return_val_if_fail (key_file != NULL, FALSE);
Packit 79f644
  g_return_val_if_fail (group != NULL, FALSE);
Packit 79f644
  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
Packit 79f644
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Packit 79f644
  return GOA_PROVIDER_GET_CLASS (self)->build_object (self,
Packit 79f644
                                                      object,
Packit 79f644
                                                      key_file,
Packit 79f644
                                                      group,
Packit 79f644
                                                      connection,
Packit 79f644
                                                      just_added,
Packit 79f644
                                                      error);
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
typedef struct
Packit 79f644
{
Packit 79f644
  GoaObject *object;
Packit 79f644
  gint expires_in;
Packit 79f644
} EnsureCredentialsData;
Packit 79f644
Packit 79f644
static EnsureCredentialsData *
Packit 79f644
ensure_credentials_data_new (GoaObject *object)
Packit 79f644
{
Packit 79f644
  EnsureCredentialsData *data;
Packit 79f644
  data = g_new0 (EnsureCredentialsData, 1);
Packit 79f644
  data->object = g_object_ref (object);
Packit 79f644
  return data;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
ensure_credentials_data_free (EnsureCredentialsData *data)
Packit 79f644
{
Packit 79f644
  g_object_unref (data->object);
Packit 79f644
  g_free (data);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
ensure_credentials_in_thread_func (GTask              *task,
Packit 79f644
                                   gpointer            object,
Packit 79f644
                                   gpointer            task_data,
Packit 79f644
                                   GCancellable       *cancellable)
Packit 79f644
{
Packit 79f644
  EnsureCredentialsData *data;
Packit 79f644
  GError *error;
Packit 79f644
Packit 79f644
  data = task_data;
Packit 79f644
Packit 79f644
  error = NULL;
Packit 79f644
  if (!goa_provider_ensure_credentials_sync (GOA_PROVIDER (object),
Packit 79f644
                                             data->object,
Packit 79f644
                                             &data->expires_in,
Packit 79f644
                                             cancellable,
Packit 79f644
                                             &error))
Packit 79f644
    g_task_return_error (task, error);
Packit 79f644
  else
Packit 79f644
    g_task_return_boolean (task, TRUE);
Packit 79f644
}
Packit 79f644
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_ensure_credentials:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 * @object: A #GoaObject with a #GoaAccount interface.
Packit 79f644
 * @cancellable: (allow-none): A #GCancellable or %NULL.
Packit 79f644
 * @callback: The function to call when the request is satisfied.
Packit 79f644
 * @user_data: Pointer to pass to @callback.
Packit 79f644
 *
Packit 79f644
 * Ensures that credentials for @object are still valid.
Packit 79f644
 *
Packit 79f644
 * When the result is ready, @callback will be called in the the 
Packit 79f644
 * linkend="g-main-context-push-thread-default">thread-default main
Packit 79f644
 * loop</link> this function was called from. You can then call
Packit 79f644
 * goa_provider_ensure_credentials_finish() to get the result
Packit 79f644
 * of the operation.
Packit 79f644
 *
Packit 79f644
 * This is a virtual method where the default implementation simply
Packit 79f644
 * throws the %GOA_ERROR_NOT_SUPPORTED error. A subclass may provide
Packit 79f644
 * another implementation.
Packit 79f644
 */
Packit 79f644
void
Packit 79f644
goa_provider_ensure_credentials (GoaProvider          *self,
Packit 79f644
                                 GoaObject            *object,
Packit 79f644
                                 GCancellable         *cancellable,
Packit 79f644
                                 GAsyncReadyCallback   callback,
Packit 79f644
                                 gpointer              user_data)
Packit 79f644
{
Packit 79f644
  GTask *task;
Packit 79f644
Packit 79f644
  g_return_if_fail (GOA_IS_PROVIDER (self));
Packit 79f644
  g_return_if_fail (GOA_IS_OBJECT (object));
Packit 79f644
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
Packit 79f644
Packit 79f644
  task = g_task_new (self, cancellable, callback, user_data);
Packit 79f644
  g_task_set_task_data (task, ensure_credentials_data_new (object), (GDestroyNotify) ensure_credentials_data_free);
Packit 79f644
  g_task_set_source_tag (task, goa_provider_ensure_credentials);
Packit 79f644
  g_task_run_in_thread (task, ensure_credentials_in_thread_func);
Packit 79f644
Packit 79f644
  g_object_unref (task);
Packit 79f644
}
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_ensure_credentials_finish:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 * @out_expires_in: (out): Return location for how long the expired credentials are good for (0 if unknown) or %NULL.
Packit 79f644
 * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to goa_provider_ensure_credentials().
Packit 79f644
 * @error: Return location for error or %NULL.
Packit 79f644
 *
Packit 79f644
 * Finishes an operation started with goa_provider_ensure_credentials().
Packit 79f644
 *
Packit 79f644
 * Returns: %TRUE if the credentials for the passed #GoaObject are valid, %FALSE if @error is set.
Packit 79f644
 */
Packit 79f644
gboolean
Packit 79f644
goa_provider_ensure_credentials_finish (GoaProvider         *self,
Packit 79f644
                                        gint                *out_expires_in,
Packit 79f644
                                        GAsyncResult        *res,
Packit 79f644
                                        GError             **error)
Packit 79f644
{
Packit 79f644
  GTask *task;
Packit 79f644
  gboolean had_error;
Packit 79f644
Packit 79f644
  gboolean ret;
Packit 79f644
  EnsureCredentialsData *data;
Packit 79f644
Packit 79f644
  ret = FALSE;
Packit 79f644
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), FALSE);
Packit 79f644
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Packit 79f644
Packit 79f644
  g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
Packit 79f644
  task = G_TASK (res);
Packit 79f644
Packit 79f644
  g_return_val_if_fail (g_task_get_source_tag (task) == goa_provider_ensure_credentials, FALSE);
Packit 79f644
Packit 79f644
  /* Workaround for bgo#764163 */
Packit 79f644
  had_error = g_task_had_error (task);
Packit 79f644
  ret = g_task_propagate_boolean (task, error);
Packit 79f644
  if (had_error)
Packit 79f644
    goto out;
Packit 79f644
Packit 79f644
  data = g_task_get_task_data (task);
Packit 79f644
  if (out_expires_in != NULL)
Packit 79f644
    *out_expires_in = data->expires_in;
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_ensure_credentials_sync:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 * @object: A #GoaObject with a #GoaAccount interface.
Packit 79f644
 * @out_expires_in: (out): Return location for how long the expired credentials are good for (0 if unknown) or %NULL.
Packit 79f644
 * @cancellable: (allow-none): A #GCancellable or %NULL.
Packit 79f644
 * @error: Return location for error or %NULL.
Packit 79f644
 *
Packit 79f644
 * Like goa_provider_ensure_credentials() but blocks the
Packit 79f644
 * calling thread until an answer is received.
Packit 79f644
 *
Packit 79f644
 * Returns: %TRUE if the credentials for the passed #GoaObject are valid, %FALSE if @error is set.
Packit 79f644
 */
Packit 79f644
gboolean
Packit 79f644
goa_provider_ensure_credentials_sync (GoaProvider     *self,
Packit 79f644
                                      GoaObject       *object,
Packit 79f644
                                      gint            *out_expires_in,
Packit 79f644
                                      GCancellable    *cancellable,
Packit 79f644
                                      GError         **error)
Packit 79f644
{
Packit 79f644
  GoaAccount *account = NULL;
Packit 79f644
  GoaProviderFeatures features;
Packit 79f644
  gboolean disabled = TRUE;
Packit 79f644
  gboolean ret = FALSE;
Packit 79f644
  guint i;
Packit 79f644
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), FALSE);
Packit 79f644
  g_return_val_if_fail (GOA_IS_OBJECT (object), FALSE);
Packit 79f644
  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
Packit 79f644
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Packit 79f644
Packit 79f644
  account = goa_object_get_account (object);
Packit 79f644
  g_return_val_if_fail (GOA_IS_ACCOUNT (account), FALSE);
Packit 79f644
Packit 79f644
  features = goa_provider_get_provider_features (self);
Packit 79f644
Packit 79f644
  for (i = 0; provider_features_info[i].property != NULL; i++)
Packit 79f644
    {
Packit 79f644
      if ((features & provider_features_info[i].feature) != 0)
Packit 79f644
        {
Packit 79f644
          gboolean feature_disabled;
Packit 79f644
Packit 79f644
          g_object_get (account, provider_features_info[i].property, &feature_disabled, NULL);
Packit 79f644
          disabled = disabled && feature_disabled;
Packit 79f644
          if (!disabled)
Packit 79f644
            break;
Packit 79f644
        }
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (disabled)
Packit 79f644
    {
Packit 79f644
      g_set_error_literal (error, GOA_ERROR, GOA_ERROR_NOT_SUPPORTED, _("Account is disabled"));
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  ret = GOA_PROVIDER_GET_CLASS (self)->ensure_credentials_sync (self, object, out_expires_in, cancellable, error);
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  if (!ret && error != NULL && *error == NULL)
Packit 79f644
    {
Packit 79f644
      const gchar *provider_type;
Packit 79f644
Packit 79f644
      provider_type = goa_provider_get_provider_type (self);
Packit 79f644
      g_critical ("GoaProvider (%s) failed to set error correctly", provider_type);
Packit 79f644
      g_set_error_literal (error, GOA_ERROR, GOA_ERROR_NOT_AUTHORIZED, _("Unknown error"));
Packit 79f644
    }
Packit 79f644
Packit 79f644
  g_clear_object (&account);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
goa_provider_ensure_credentials_sync_real (GoaProvider   *self,
Packit 79f644
                                           GoaObject     *object,
Packit 79f644
                                           gint          *out_expires_in,
Packit 79f644
                                           GCancellable  *cancellable,
Packit 79f644
                                           GError       **error)
Packit 79f644
{
Packit 79f644
  g_set_error (error,
Packit 79f644
               GOA_ERROR,
Packit 79f644
               GOA_ERROR_NOT_SUPPORTED,
Packit 79f644
               _("ensure_credentials_sync is not implemented on type %s"),
Packit 79f644
               g_type_name (G_TYPE_FROM_INSTANCE (self)));
Packit 79f644
  return FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
goa_provider_build_object_real (GoaProvider         *self,
Packit 79f644
                                GoaObjectSkeleton   *object,
Packit 79f644
                                GKeyFile            *key_file,
Packit 79f644
                                const gchar         *group,
Packit 79f644
                                GDBusConnection     *connection,
Packit 79f644
                                gboolean             just_added,
Packit 79f644
                                GError             **error)
Packit 79f644
{
Packit 79f644
  /* does nothing */
Packit 79f644
  return TRUE;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_get_credentials_generation:
Packit 79f644
 * @self: A #GoaProvider.
Packit 79f644
 *
Packit 79f644
 * Gets the generation of credentials being used for the provider.
Packit 79f644
 *
Packit 79f644
 * Implementations should bump this number when changes are introduced
Packit 79f644
 * that may render existing credentials unusable.
Packit 79f644
 *
Packit 79f644
 * For example, if an additional scope is requested (e.g. access to
Packit 79f644
 * contacts data) while obtaining credentials, then this number needs
Packit 79f644
 * to be bumped since existing credentials are not good for the added
Packit 79f644
 * scope.
Packit 79f644
 *
Packit 79f644
 * This is a virtual method where the default implementation returns
Packit 79f644
 * 0.
Packit 79f644
 *
Packit 79f644
 * Returns: The current generation of credentials.
Packit 79f644
 */
Packit 79f644
guint
Packit 79f644
goa_provider_get_credentials_generation (GoaProvider *self)
Packit 79f644
{
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), 0);
Packit 79f644
  return GOA_PROVIDER_GET_CLASS (self)->get_credentials_generation (self);
Packit 79f644
}
Packit 79f644
Packit 79f644
static guint
Packit 79f644
goa_provider_get_credentials_generation_real (GoaProvider *self)
Packit 79f644
{
Packit 79f644
  return 0;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
void
Packit 79f644
goa_provider_ensure_extension_points_registered (void)
Packit 79f644
{
Packit 79f644
  static gsize once_init_value = 0;
Packit 79f644
Packit 79f644
  if (g_once_init_enter (&once_init_value))
Packit 79f644
    {
Packit 79f644
      GIOExtensionPoint *extension_point;
Packit 79f644
Packit 79f644
      extension_point = g_io_extension_point_register (GOA_PROVIDER_EXTENSION_POINT_NAME);
Packit 79f644
      g_io_extension_point_set_required_type (extension_point, GOA_TYPE_PROVIDER);
Packit 79f644
Packit 79f644
      extension_point = g_io_extension_point_register (GOA_PROVIDER_FACTORY_EXTENSION_POINT_NAME);
Packit 79f644
      g_io_extension_point_set_required_type (extension_point, GOA_TYPE_PROVIDER_FACTORY);
Packit 79f644
Packit 79f644
      g_once_init_leave (&once_init_value, 1);
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static struct
Packit 79f644
{
Packit 79f644
  const gchar *name;
Packit 79f644
  GType (*get_type) (void);
Packit 79f644
} ordered_builtins_map[] = {
Packit 79f644
  /* The order in which the providers' types are created is
Packit 79f644
   * important because it affects the order in which they are
Packit 79f644
   * returned by goa_provider_get_all.
Packit 79f644
   */
Packit 79f644
#ifdef GOA_GOOGLE_ENABLED
Packit 79f644
  { GOA_GOOGLE_NAME, goa_google_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_OWNCLOUD_ENABLED
Packit 79f644
  { GOA_OWNCLOUD_NAME, goa_owncloud_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_FACEBOOK_ENABLED
Packit 79f644
  { GOA_FACEBOOK_NAME, goa_facebook_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_WINDOWS_LIVE_ENABLED
Packit 79f644
  { GOA_WINDOWS_LIVE_NAME, goa_windows_live_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_FLICKR_ENABLED
Packit 79f644
  { GOA_FLICKR_NAME, goa_flickr_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_POCKET_ENABLED
Packit 79f644
  { GOA_POCKET_NAME, goa_pocket_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_FOURSQUARE_ENABLED
Packit 79f644
  { GOA_FOURSQUARE_NAME, goa_foursquare_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_EXCHANGE_ENABLED
Packit 79f644
  { GOA_EXCHANGE_NAME, goa_exchange_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_LASTFM_ENABLED
Packit 79f644
  { GOA_LASTFM_NAME, goa_lastfm_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_TODOIST_ENABLED
Packit 79f644
  { GOA_TODOIST_NAME, goa_todoist_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_IMAP_SMTP_ENABLED
Packit 79f644
  { GOA_IMAP_SMTP_NAME, goa_imap_smtp_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_KERBEROS_ENABLED
Packit 79f644
  { GOA_KERBEROS_NAME, goa_kerberos_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_MEDIA_SERVER_ENABLED
Packit 79f644
  { GOA_MEDIA_SERVER_NAME, goa_media_server_provider_get_type },
Packit 79f644
#endif
Packit 79f644
#ifdef GOA_TELEPATHY_ENABLED
Packit 79f644
  { GOA_TELEPATHY_NAME, goa_telepathy_factory_get_type },
Packit 79f644
#endif
Packit 79f644
  { NULL, NULL }
Packit 79f644
};
Packit 79f644
Packit 79f644
void
Packit 79f644
goa_provider_ensure_builtins_loaded (void)
Packit 79f644
{
Packit 79f644
  static gsize once_init_value = 0;
Packit 79f644
Packit 79f644
  goa_provider_ensure_extension_points_registered ();
Packit 79f644
Packit 79f644
  if (g_once_init_enter (&once_init_value))
Packit 79f644
    {
Packit 79f644
      GSettings *settings;
Packit 79f644
      gchar **whitelisted_providers;
Packit 79f644
      guint i;
Packit 79f644
      guint j;
Packit 79f644
      gboolean all = FALSE;
Packit 79f644
Packit 79f644
      settings = g_settings_new (GOA_SETTINGS_SCHEMA);
Packit 79f644
      whitelisted_providers = g_settings_get_strv (settings, GOA_SETTINGS_WHITELISTED_PROVIDERS);
Packit 79f644
Packit 79f644
      /* Enable everything if there is 'all'. */
Packit 79f644
      for (i = 0; whitelisted_providers[i] != NULL; i++)
Packit 79f644
        {
Packit 79f644
          if (g_strcmp0 (whitelisted_providers[i], "all") == 0)
Packit 79f644
            {
Packit 79f644
              g_debug ("Loading all providers: ");
Packit 79f644
              for (j = 0; ordered_builtins_map[j].name != NULL; j++)
Packit 79f644
                {
Packit 79f644
                  g_debug (" - %s", ordered_builtins_map[j].name);
Packit 79f644
                  g_type_ensure ((*ordered_builtins_map[j].get_type) ());
Packit 79f644
                }
Packit 79f644
Packit 79f644
              all = TRUE;
Packit 79f644
              break;
Packit 79f644
            }
Packit 79f644
        }
Packit 79f644
Packit 79f644
      if (all)
Packit 79f644
        goto cleanup;
Packit 79f644
Packit 79f644
      /* Otherwise try them one by one. */
Packit 79f644
      g_debug ("Loading whitelisted providers: ");
Packit 79f644
      for (i = 0; ordered_builtins_map[i].name != NULL; i++)
Packit 79f644
        {
Packit 79f644
          for (j = 0; whitelisted_providers[j] != NULL; j++)
Packit 79f644
            {
Packit 79f644
              if (g_strcmp0 (whitelisted_providers[j], ordered_builtins_map[i].name) == 0)
Packit 79f644
                {
Packit 79f644
                  g_debug (" - %s", ordered_builtins_map[j].name);
Packit 79f644
                  g_type_ensure ((*ordered_builtins_map[i].get_type) ());
Packit 79f644
                  break;
Packit 79f644
                }
Packit 79f644
            }
Packit 79f644
        }
Packit 79f644
Packit 79f644
    cleanup:
Packit 79f644
      g_strfreev (whitelisted_providers);
Packit 79f644
      g_object_unref (settings);
Packit 79f644
      g_once_init_leave (&once_init_value, 1);
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_get_for_provider_type:
Packit 79f644
 * @provider_type: A provider type.
Packit 79f644
 *
Packit 79f644
 * Returns a #GoaProvider for @provider_type (if available).
Packit 79f644
 *
Packit 79f644
 * If @provider_type doesn't contain any "/", a
Packit 79f644
 * %GOA_PROVIDER_EXTENSION_POINT_NAME extension for @provider_type is looked up
Packit 79f644
 * and the newly created #GoaProvider, if any, is returned.
Packit 79f644
 *
Packit 79f644
 * If @provider_type contains a "/", a
Packit 79f644
 * %GOA_PROVIDER_FACTORY_EXTENSION_POINT_NAME extension for the first part of
Packit 79f644
 * @provider_type is looked up. If found, the #GoaProviderFactory is used
Packit 79f644
 * to create a dynamic #GoaProvider matching the second part of @provider_type.
Packit 79f644
 *
Packit 79f644
 * Returns: (transfer full): A #GoaProvider (that must be freed
Packit 79f644
 * with g_object_unref()) or %NULL if not found.
Packit 79f644
 */
Packit 79f644
GoaProvider *
Packit 79f644
goa_provider_get_for_provider_type (const gchar *provider_type)
Packit 79f644
{
Packit 79f644
  GIOExtension *extension;
Packit 79f644
  GIOExtensionPoint *extension_point;
Packit 79f644
  gchar **split_provider_type;
Packit 79f644
  GoaProvider *ret;
Packit 79f644
Packit 79f644
  g_return_val_if_fail (provider_type != NULL, NULL);
Packit 79f644
Packit 79f644
  goa_provider_ensure_builtins_loaded ();
Packit 79f644
Packit 79f644
  ret = NULL;
Packit 79f644
Packit 79f644
  split_provider_type = g_strsplit (provider_type, "/", 2);
Packit 79f644
Packit 79f644
  if (g_strv_length (split_provider_type) == 1)
Packit 79f644
    {
Packit 79f644
      /* Normal provider */
Packit 79f644
      extension_point = g_io_extension_point_lookup (GOA_PROVIDER_EXTENSION_POINT_NAME);
Packit 79f644
      extension = g_io_extension_point_get_extension_by_name (extension_point, provider_type);
Packit 79f644
      if (extension != NULL)
Packit 79f644
        ret = GOA_PROVIDER (g_object_new (g_io_extension_get_type (extension), NULL));
Packit 79f644
    }
Packit 79f644
  else
Packit 79f644
    {
Packit 79f644
      /* Dynamic provider created through a factory */
Packit 79f644
      extension_point = g_io_extension_point_lookup (GOA_PROVIDER_FACTORY_EXTENSION_POINT_NAME);
Packit 79f644
      extension = g_io_extension_point_get_extension_by_name (extension_point, split_provider_type[0]);
Packit 79f644
      if (extension != NULL)
Packit 79f644
        {
Packit 79f644
          GoaProviderFactory *factory = g_object_new (g_io_extension_get_type (extension), NULL);
Packit 79f644
          ret = goa_provider_factory_get_provider (factory, split_provider_type[1]);
Packit 79f644
          g_object_unref (factory);
Packit 79f644
        }
Packit 79f644
    }
Packit 79f644
Packit 79f644
  g_strfreev (split_provider_type);
Packit 79f644
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
typedef struct
Packit 79f644
{
Packit 79f644
  GQueue ret;
Packit 79f644
  gint pending_calls;
Packit 79f644
  GTask *task;
Packit 79f644
} GetAllData;
Packit 79f644
Packit 79f644
static void
Packit 79f644
free_list_and_unref (gpointer data)
Packit 79f644
{
Packit 79f644
  g_list_free_full (data, g_object_unref);
Packit 79f644
}
Packit 79f644
Packit 79f644
static gint
Packit 79f644
compare_providers (GoaProvider *a,
Packit 79f644
                   GoaProvider *b)
Packit 79f644
{
Packit 79f644
  gboolean a_branded;
Packit 79f644
  gboolean b_branded;
Packit 79f644
Packit 79f644
  if (goa_provider_get_provider_features (a) & GOA_PROVIDER_FEATURE_BRANDED)
Packit 79f644
    a_branded = TRUE;
Packit 79f644
  else
Packit 79f644
    a_branded = FALSE;
Packit 79f644
Packit 79f644
  if (goa_provider_get_provider_features (b) & GOA_PROVIDER_FEATURE_BRANDED)
Packit 79f644
    b_branded = TRUE;
Packit 79f644
  else
Packit 79f644
    b_branded = FALSE;
Packit 79f644
Packit 79f644
  /* g_queue_sort() uses a stable sort, so, if we return 0, the order
Packit 79f644
   * is not changed. */
Packit 79f644
  if (a_branded == b_branded)
Packit 79f644
    return 0;
Packit 79f644
  else if (a_branded)
Packit 79f644
    return -1;
Packit 79f644
  else
Packit 79f644
    return 1;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
get_all_check_done (GetAllData *data)
Packit 79f644
{
Packit 79f644
  if (data->pending_calls > 0)
Packit 79f644
    return;
Packit 79f644
Packit 79f644
  /* Make sure that branded providers come first, but don't change the
Packit 79f644
   * order otherwise. */
Packit 79f644
  g_queue_sort (&data->ret, (GCompareDataFunc) compare_providers, NULL);
Packit 79f644
Packit 79f644
  /* Steal the list out of the GQueue. */
Packit 79f644
  g_task_return_pointer (data->task, data->ret.head, free_list_and_unref);
Packit 79f644
Packit 79f644
  g_object_unref (data->task);
Packit 79f644
  g_slice_free (GetAllData, data);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
get_providers_cb (GObject      *source,
Packit 79f644
                  GAsyncResult *res,
Packit 79f644
                  gpointer      user_data)
Packit 79f644
{
Packit 79f644
  GoaProviderFactory *factory = GOA_PROVIDER_FACTORY (source);
Packit 79f644
  GetAllData *data = user_data;
Packit 79f644
  GList *providers = NULL;
Packit 79f644
  GList *l;
Packit 79f644
  GError *error = NULL;
Packit 79f644
Packit 79f644
  if (!goa_provider_factory_get_providers_finish (factory, &providers, res, &error))
Packit 79f644
    {
Packit 79f644
      g_critical ("Error getting providers from a factory: %s (%s, %d)",
Packit 79f644
          error->message,
Packit 79f644
          g_quark_to_string (error->domain),
Packit 79f644
          error->code);
Packit 79f644
      g_clear_error (&error);
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  for (l = providers; l != NULL; l = l->next)
Packit 79f644
    {
Packit 79f644
      /* Steal the value */
Packit 79f644
      g_queue_push_tail (&data->ret, l->data);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  g_list_free (providers);
Packit 79f644
Packit 79f644
out:
Packit 79f644
  data->pending_calls--;
Packit 79f644
  get_all_check_done (data);
Packit 79f644
}
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_get_all:
Packit 79f644
 * @callback: The function to call when the request is satisfied.
Packit 79f644
 * @user_data: Pointer to pass to @callback.
Packit 79f644
 *
Packit 79f644
 * Creates a list of all the available #GoaProvider instances.
Packit 79f644
 *
Packit 79f644
 * When the result is ready, @callback will be called in the the 
Packit 79f644
 * linkend="g-main-context-push-thread-default">thread-default main
Packit 79f644
 * loop</link> this function was called from. You can then call
Packit 79f644
 * goa_provider_get_all_finish() to get the result of the operation.
Packit 79f644
 *
Packit 79f644
 * See goa_provider_get_for_provider_type() for details on how the providers
Packit 79f644
 * are found.
Packit 79f644
 */
Packit 79f644
void
Packit 79f644
goa_provider_get_all (GAsyncReadyCallback callback,
Packit 79f644
                      gpointer            user_data)
Packit 79f644
{
Packit 79f644
  GList *extensions;
Packit 79f644
  GList *l;
Packit 79f644
  GIOExtensionPoint *extension_point;
Packit 79f644
  GetAllData *data;
Packit 79f644
  gint i;
Packit 79f644
Packit 79f644
  goa_provider_ensure_builtins_loaded ();
Packit 79f644
Packit 79f644
  data = g_slice_new0 (GetAllData);
Packit 79f644
  data->task = g_task_new (NULL, NULL, callback, user_data);
Packit 79f644
  g_task_set_source_tag (data->task, goa_provider_get_all);
Packit 79f644
  g_queue_init (&data->ret);
Packit 79f644
Packit 79f644
  /* Load the normal providers. */
Packit 79f644
  extension_point = g_io_extension_point_lookup (GOA_PROVIDER_EXTENSION_POINT_NAME);
Packit 79f644
  extensions = g_io_extension_point_get_extensions (extension_point);
Packit 79f644
  /* TODO: what if there are two extensions with the same name? */
Packit 79f644
  for (l = extensions, i = 0; l != NULL; l = l->next, i++)
Packit 79f644
    {
Packit 79f644
      GIOExtension *extension = l->data;
Packit 79f644
      /* The extensions are loaded in the reverse order we used in
Packit 79f644
       * goa_provider_ensure_builtins_loaded, so we need to push
Packit 79f644
       * extension if front of the already loaded ones. */
Packit 79f644
      g_queue_push_head (&data->ret, g_object_new (g_io_extension_get_type (extension), NULL));
Packit 79f644
    }
Packit 79f644
Packit 79f644
  /* Load the provider factories and get the dynamic providers out of them. */
Packit 79f644
  extension_point = g_io_extension_point_lookup (GOA_PROVIDER_FACTORY_EXTENSION_POINT_NAME);
Packit 79f644
  extensions = g_io_extension_point_get_extensions (extension_point);
Packit 79f644
  for (l = extensions, i = 0; l != NULL; l = l->next, i++)
Packit 79f644
    {
Packit 79f644
      GIOExtension *extension = l->data;
Packit 79f644
      GoaProviderFactory *factory;
Packit 79f644
Packit 79f644
      factory = GOA_PROVIDER_FACTORY (g_object_new (g_io_extension_get_type (extension), NULL));
Packit 79f644
      goa_provider_factory_get_providers (factory, get_providers_cb, data);
Packit 79f644
      g_object_unref (factory);
Packit 79f644
      data->pending_calls++;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  get_all_check_done (data);
Packit 79f644
}
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_get_all_finish:
Packit 79f644
 * @out_providers: (out) (transfer full) (element-type GoaProvider):
Packit 79f644
 * Return location for a list of #GoaProvider instances.
Packit 79f644
 * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to goa_provider_get_all().
Packit 79f644
 * @error: Return location for error or %NULL.
Packit 79f644
 *
Packit 79f644
 * Finishes an operation started with goa_provider_get_all().
Packit 79f644
 *
Packit 79f644
 * Returns: %TRUE if the list was successfully retrieved, %FALSE if @error is set.
Packit 79f644
 */
Packit 79f644
gboolean
Packit 79f644
goa_provider_get_all_finish (GList        **out_providers,
Packit 79f644
                             GAsyncResult  *result,
Packit 79f644
                             GError       **error)
Packit 79f644
{
Packit 79f644
  GTask *task;
Packit 79f644
  GList *providers;
Packit 79f644
  gboolean had_error;
Packit 79f644
Packit 79f644
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Packit 79f644
Packit 79f644
  g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE);
Packit 79f644
  task = G_TASK (result);
Packit 79f644
Packit 79f644
  g_return_val_if_fail (g_task_get_source_tag (task) == goa_provider_get_all, FALSE);
Packit 79f644
Packit 79f644
  /* Workaround for bgo#764163 */
Packit 79f644
  had_error = g_task_had_error (task);
Packit 79f644
  providers = g_task_propagate_pointer (task, error);
Packit 79f644
  if (had_error)
Packit 79f644
    return FALSE;
Packit 79f644
Packit 79f644
  if (out_providers != NULL)
Packit 79f644
    {
Packit 79f644
      *out_providers = providers;
Packit 79f644
      providers = NULL;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  g_list_free_full (providers, g_object_unref);
Packit 79f644
  return TRUE;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
void
Packit 79f644
goa_provider_remove_account (GoaProvider          *self,
Packit 79f644
                             GoaObject            *object,
Packit 79f644
                             GCancellable         *cancellable,
Packit 79f644
                             GAsyncReadyCallback   callback,
Packit 79f644
                             gpointer              user_data)
Packit 79f644
{
Packit 79f644
  g_return_if_fail (GOA_IS_PROVIDER (self));
Packit 79f644
  g_return_if_fail (GOA_IS_OBJECT (object));
Packit 79f644
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
Packit 79f644
Packit 79f644
  GOA_PROVIDER_GET_CLASS (self)->remove_account (self, object, cancellable, callback, user_data);
Packit 79f644
}
Packit 79f644
Packit 79f644
gboolean
Packit 79f644
goa_provider_remove_account_finish (GoaProvider   *self,
Packit 79f644
                                    GAsyncResult  *res,
Packit 79f644
                                    GError       **error)
Packit 79f644
{
Packit 79f644
  g_return_val_if_fail (GOA_IS_PROVIDER (self), FALSE);
Packit 79f644
  g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
Packit 79f644
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Packit 79f644
Packit 79f644
  return GOA_PROVIDER_GET_CLASS (self)->remove_account_finish (self, res, error);
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_provider_remove_account_real (GoaProvider          *self,
Packit 79f644
                                  GoaObject            *object,
Packit 79f644
                                  GCancellable         *cancellable,
Packit 79f644
                                  GAsyncReadyCallback   callback,
Packit 79f644
                                  gpointer              user_data)
Packit 79f644
{
Packit 79f644
  GTask *task;
Packit 79f644
Packit 79f644
  task = g_task_new (self, cancellable, callback, user_data);
Packit 79f644
  g_task_set_source_tag (task, goa_provider_remove_account_real);
Packit 79f644
  g_task_return_boolean (task, TRUE);
Packit 79f644
  g_object_unref (task);
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
goa_provider_remove_account_finish_real (GoaProvider   *self,
Packit 79f644
                                         GAsyncResult  *res,
Packit 79f644
                                         GError       **error)
Packit 79f644
{
Packit 79f644
  GTask *task;
Packit 79f644
Packit 79f644
  g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
Packit 79f644
  task = G_TASK (res);
Packit 79f644
Packit 79f644
  g_return_val_if_fail (g_task_get_source_tag (task) == goa_provider_remove_account_real, FALSE);
Packit 79f644
Packit 79f644
  return g_task_propagate_boolean (task, error);
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_set_preseed_data:
Packit 79f644
 * @self: The #GoaProvider
Packit 79f644
 * @preseed_data: A #GVariant of type a{sv}
Packit 79f644
 *
Packit 79f644
 * Sets the #GoaProvider:preseed-data property to feed any information already
Packit 79f644
 * collected that can be useful when creating a new account.
Packit 79f644
 *
Packit 79f644
 * If the @preseed_data #GVariant is floating, it is consumed to allow
Packit 79f644
 * 'inline' use of the g_variant_new() family of functions.
Packit 79f644
 *
Packit 79f644
 * Deprecated: 3.28: This function does nothing.
Packit 79f644
 */
Packit 79f644
void
Packit 79f644
goa_provider_set_preseed_data (GoaProvider *self,
Packit 79f644
                               GVariant    *preseed_data)
Packit 79f644
{
Packit 79f644
}
Packit 79f644
Packit 79f644
/**
Packit 79f644
 * goa_provider_get_preseed_data:
Packit 79f644
 * @self: The #GoaProvider
Packit 79f644
 *
Packit 79f644
 * Gets the #GVariant set through the #GoaProvider:preseed-data property.
Packit 79f644
 *
Packit 79f644
 * Returns: (transfer none): A #GVariant that is known to be valid until
Packit 79f644
 *   the property is overridden or the provider freed.
Packit 79f644
 *
Packit 79f644
 * Deprecated: 3.28: This function does nothing.
Packit 79f644
 */
Packit 79f644
GVariant *
Packit 79f644
goa_provider_get_preseed_data (GoaProvider *self)
Packit 79f644
{
Packit 79f644
  return NULL;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
GtkWidget *
Packit 79f644
goa_util_add_row_widget (GtkGrid      *grid,
Packit 79f644
                         gint          row,
Packit 79f644
                         const gchar  *label_text,
Packit 79f644
                         GtkWidget    *widget)
Packit 79f644
{
Packit 79f644
  GtkWidget *label;
Packit 79f644
Packit 79f644
  g_return_val_if_fail (GTK_IS_GRID (grid), NULL);
Packit 79f644
  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
Packit 79f644
Packit 79f644
  if (label_text != NULL)
Packit 79f644
    {
Packit 79f644
      GtkStyleContext *context;
Packit 79f644
Packit 79f644
      label = gtk_label_new (label_text);
Packit 79f644
      context = gtk_widget_get_style_context (label);
Packit 79f644
      gtk_style_context_add_class (context, GTK_STYLE_CLASS_DIM_LABEL);
Packit 79f644
      gtk_widget_set_halign (label, GTK_ALIGN_END);
Packit 79f644
      gtk_widget_set_hexpand (label, TRUE);
Packit 79f644
      gtk_grid_attach (grid, label, 0, row, 1, 1);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  gtk_grid_attach (grid, widget, 1, row, 3, 1);
Packit 79f644
  return widget;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
gchar *
Packit 79f644
goa_util_lookup_keyfile_string (GoaObject    *object,
Packit 79f644
                                const gchar  *key)
Packit 79f644
{
Packit 79f644
  GoaAccount *account;
Packit 79f644
  GError *error;
Packit 79f644
  GKeyFile *key_file;
Packit 79f644
  gchar *path;
Packit 79f644
  gchar *group;
Packit 79f644
  gchar *ret;
Packit 79f644
Packit 79f644
  ret = NULL;
Packit 79f644
Packit 79f644
  account = goa_object_peek_account (object);
Packit 79f644
  path = g_strdup_printf ("%s/goa-1.0/accounts.conf", g_get_user_config_dir ());
Packit 79f644
  group = g_strdup_printf ("Account %s", goa_account_get_id (account));
Packit 79f644
Packit 79f644
  key_file = g_key_file_new ();
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
      g_warning ("Error loading keyfile %s: %s (%s, %d)",
Packit 79f644
                 path,
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
  ret = g_key_file_get_string (key_file,
Packit 79f644
                               group,
Packit 79f644
                               key,
Packit 79f644
                               &error);
Packit 79f644
  if (ret == NULL)
Packit 79f644
    {
Packit 79f644
      /* this is not fatal (think upgrade-path) */
Packit 79f644
      g_debug ("Error getting value for key %s in group `%s' from keyfile %s: %s (%s, %d)",
Packit 79f644
               key,
Packit 79f644
               group,
Packit 79f644
               path,
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
 out:
Packit 79f644
  g_key_file_unref (key_file);
Packit 79f644
  g_free (group);
Packit 79f644
  g_free (path);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
gboolean
Packit 79f644
goa_util_lookup_keyfile_boolean (GoaObject    *object,
Packit 79f644
                                 const gchar  *key)
Packit 79f644
{
Packit 79f644
  GoaAccount *account;
Packit 79f644
  GError *error;
Packit 79f644
  GKeyFile *key_file;
Packit 79f644
  gchar *path;
Packit 79f644
  gchar *group;
Packit 79f644
  gboolean ret;
Packit 79f644
Packit 79f644
  ret = FALSE;
Packit 79f644
Packit 79f644
  account = goa_object_peek_account (object);
Packit 79f644
  path = g_strdup_printf ("%s/goa-1.0/accounts.conf", g_get_user_config_dir ());
Packit 79f644
  group = g_strdup_printf ("Account %s", goa_account_get_id (account));
Packit 79f644
Packit 79f644
  key_file = g_key_file_new ();
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
      g_warning ("Error loading keyfile %s: %s (%s, %d)",
Packit 79f644
                 path,
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
  ret = g_key_file_get_boolean (key_file,
Packit 79f644
                                group,
Packit 79f644
                                key,
Packit 79f644
                                &error);
Packit 79f644
  if (error != NULL)
Packit 79f644
    {
Packit 79f644
      /* this is not fatal (think upgrade-path) */
Packit 79f644
      g_debug ("Error getting boolean value for key %s in group `%s' from keyfile %s: %s (%s, %d)",
Packit 79f644
               key,
Packit 79f644
               group,
Packit 79f644
               path,
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
 out:
Packit 79f644
  g_key_file_unref (key_file);
Packit 79f644
  g_free (group);
Packit 79f644
  g_free (path);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
void
Packit 79f644
goa_util_account_notify_property_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
Packit 79f644
{
Packit 79f644
  GoaAccount *account;
Packit 79f644
  gboolean value;
Packit 79f644
  const gchar *key;
Packit 79f644
  const gchar *name;
Packit 79f644
Packit 79f644
  g_return_if_fail (GOA_IS_ACCOUNT (object));
Packit 79f644
Packit 79f644
  account = GOA_ACCOUNT (object);
Packit 79f644
  key = user_data;
Packit 79f644
  name = g_param_spec_get_name (pspec);
Packit 79f644
Packit 79f644
  g_object_get (account, name, &value, NULL);
Packit 79f644
  goa_utils_keyfile_set_boolean (account, key, !value);
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
GtkWidget *
Packit 79f644
goa_util_add_row_switch_from_keyfile_with_blurb (GtkGrid      *grid,
Packit 79f644
                                                 gint          row,
Packit 79f644
                                                 GoaObject    *object,
Packit 79f644
                                                 const gchar  *label_text,
Packit 79f644
                                                 const gchar  *property,
Packit 79f644
                                                 const gchar  *blurb)
Packit 79f644
{
Packit 79f644
  GoaAccount *account;
Packit 79f644
  GtkWidget *hbox;
Packit 79f644
  GtkWidget *switch_;
Packit 79f644
  gboolean value;
Packit 79f644
Packit 79f644
  account = goa_object_peek_account (object);
Packit 79f644
  g_object_get (account, property, &value, NULL);
Packit 79f644
  switch_ = gtk_switch_new ();
Packit 79f644
Packit 79f644
  if (goa_account_get_attention_needed (account))
Packit 79f644
    {
Packit 79f644
      gtk_widget_set_sensitive (switch_, FALSE);
Packit 79f644
      gtk_switch_set_active (GTK_SWITCH (switch_), FALSE);
Packit 79f644
    }
Packit 79f644
  else
Packit 79f644
    {
Packit 79f644
      gtk_switch_set_active (GTK_SWITCH (switch_), !value);
Packit 79f644
      g_object_bind_property (switch_, "active",
Packit 79f644
                              account, property,
Packit 79f644
                              G_BINDING_BIDIRECTIONAL | G_BINDING_INVERT_BOOLEAN);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
Packit 79f644
  gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE);
Packit 79f644
Packit 79f644
  if (blurb != NULL)
Packit 79f644
    {
Packit 79f644
      GtkWidget *label;
Packit 79f644
Packit 79f644
      label = gtk_label_new_with_mnemonic (blurb);
Packit 79f644
      gtk_label_set_mnemonic_widget (GTK_LABEL (label), switch_);
Packit 79f644
      gtk_label_set_width_chars (GTK_LABEL (label), 18);
Packit 79f644
      gtk_label_set_xalign (GTK_LABEL (label), 0.0);
Packit 79f644
      gtk_container_add (GTK_CONTAINER (hbox), label);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  gtk_container_add (GTK_CONTAINER (hbox), switch_);
Packit 79f644
  goa_util_add_row_widget (grid, row, label_text, hbox);
Packit 79f644
  return switch_;
Packit 79f644
}