Blame src/goabackend/goalastfmprovider.c

Packit Service c6b9b0
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
Packit Service c6b9b0
/*
Packit Service c6b9b0
 * Copyright © 2015 Felipe Borges
Packit Service c6b9b0
 *
Packit Service c6b9b0
 * This library is free software; you can redistribute it and/or
Packit Service c6b9b0
 * modify it under the terms of the GNU Lesser General Public
Packit Service c6b9b0
 * License as published by the Free Software Foundation; either
Packit Service c6b9b0
 * version 2 of the License, or (at your option) any later version.
Packit Service c6b9b0
 *
Packit Service c6b9b0
 * This library is distributed in the hope that it will be useful,
Packit Service c6b9b0
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service c6b9b0
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service c6b9b0
 * Lesser General Public License for more details.
Packit Service c6b9b0
 *
Packit Service c6b9b0
 * You should have received a copy of the GNU Lesser General
Packit Service c6b9b0
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit Service c6b9b0
 */
Packit Service c6b9b0
Packit Service c6b9b0
#include "config.h"
Packit Service c6b9b0
#include <glib/gi18n-lib.h>
Packit Service c6b9b0
Packit Service c6b9b0
#include <rest/rest-proxy.h>
Packit Service c6b9b0
#include <json-glib/json-glib.h>
Packit Service c6b9b0
Packit Service c6b9b0
#include "goahttpclient.h"
Packit Service c6b9b0
#include "goaprovider.h"
Packit Service c6b9b0
#include "goaprovider-priv.h"
Packit Service c6b9b0
#include "goaoauth2provider.h"
Packit Service c6b9b0
#include "goaoauth2provider-priv.h"
Packit Service c6b9b0
#include "goalastfmprovider.h"
Packit Service c6b9b0
#include "goarestproxy.h"
Packit Service c6b9b0
#include "goautils.h"
Packit Service c6b9b0
Packit Service c6b9b0
struct _GoaLastfmProvider
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaOAuth2Provider parent_instance;
Packit Service c6b9b0
};
Packit Service c6b9b0
Packit Service c6b9b0
typedef struct _GoaLastfmProviderClass GoaLastfmProviderClass;
Packit Service c6b9b0
Packit Service c6b9b0
struct _GoaLastfmProviderClass
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaOAuth2ProviderClass parent_class;
Packit Service c6b9b0
};
Packit Service c6b9b0
Packit Service c6b9b0
G_DEFINE_TYPE_WITH_CODE (GoaLastfmProvider, goa_lastfm_provider, GOA_TYPE_OAUTH2_PROVIDER,
Packit Service c6b9b0
                         goa_provider_ensure_extension_points_registered ();
Packit Service c6b9b0
                         g_io_extension_point_implement (GOA_PROVIDER_EXTENSION_POINT_NAME,
Packit Service c6b9b0
                                                         g_define_type_id,
Packit Service c6b9b0
                                                         GOA_LASTFM_NAME,
Packit Service c6b9b0
                                                         0));
Packit Service c6b9b0
Packit Service c6b9b0
/* ---------------------------------------------------------------------------------------------------- */
Packit Service c6b9b0
Packit Service c6b9b0
static const gchar *
Packit Service c6b9b0
get_provider_type (GoaProvider *_provider)
Packit Service c6b9b0
{
Packit Service c6b9b0
  return GOA_LASTFM_NAME;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static gchar *
Packit Service c6b9b0
get_provider_name (GoaProvider *_provider,
Packit Service c6b9b0
                   GoaObject   *object)
Packit Service c6b9b0
{
Packit Service c6b9b0
  return g_strdup (_("Last.fm"));
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static GoaProviderGroup
Packit Service c6b9b0
get_provider_group (GoaProvider *_provider)
Packit Service c6b9b0
{
Packit Service c6b9b0
  return GOA_PROVIDER_GROUP_BRANDED;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static GoaProviderFeatures
Packit Service c6b9b0
get_provider_features (GoaProvider *_provider)
Packit Service c6b9b0
{
Packit Service c6b9b0
  return GOA_PROVIDER_FEATURE_BRANDED | GOA_PROVIDER_FEATURE_MUSIC;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static const gchar *
Packit Service c6b9b0
get_request_uri (GoaProvider *provider)
Packit Service c6b9b0
{
Packit Service c6b9b0
  return "https://ws.audioscrobbler.com/2.0/";
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static const gchar *
Packit Service c6b9b0
get_client_id (GoaOAuth2Provider *provider)
Packit Service c6b9b0
{
Packit Service c6b9b0
    return GOA_LASTFM_CLIENT_ID;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static const gchar *
Packit Service c6b9b0
get_client_secret (GoaOAuth2Provider *provider)
Packit Service c6b9b0
{
Packit Service c6b9b0
    return GOA_LASTFM_CLIENT_SECRET;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
/* ---------------------------------------------------------------------------------------------------- */
Packit Service c6b9b0
Packit Service c6b9b0
static gboolean
Packit Service c6b9b0
build_object (GoaProvider         *provider,
Packit Service c6b9b0
              GoaObjectSkeleton   *object,
Packit Service c6b9b0
              GKeyFile            *key_file,
Packit Service c6b9b0
              const gchar         *group,
Packit Service c6b9b0
              GDBusConnection     *connection,
Packit Service c6b9b0
              gboolean             just_added,
Packit Service c6b9b0
              GError             **error)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaAccount *account;
Packit Service c6b9b0
  GoaMusic *music = NULL;
Packit Service c6b9b0
  gboolean music_enabled;
Packit Service c6b9b0
  gboolean ret = FALSE;
Packit Service c6b9b0
Packit Service c6b9b0
  account = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  /* Chain up */
Packit Service c6b9b0
  if (!GOA_PROVIDER_CLASS (goa_lastfm_provider_parent_class)->build_object (provider,
Packit Service c6b9b0
                                                                            object,
Packit Service c6b9b0
                                                                            key_file,
Packit Service c6b9b0
                                                                            group,
Packit Service c6b9b0
                                                                            connection,
Packit Service c6b9b0
                                                                            just_added,
Packit Service c6b9b0
                                                                            error))
Packit Service c6b9b0
    goto out;
Packit Service c6b9b0
Packit Service c6b9b0
  account = goa_object_get_account (GOA_OBJECT (object));
Packit Service c6b9b0
Packit Service c6b9b0
  /* Music */
Packit Service c6b9b0
  music = goa_object_get_music (GOA_OBJECT (object));
Packit Service c6b9b0
  music_enabled = g_key_file_get_boolean (key_file, group, "MusicEnabled", NULL);
Packit Service c6b9b0
  if (music_enabled)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      if (music == NULL)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          music = goa_music_skeleton_new ();
Packit Service c6b9b0
          goa_object_skeleton_set_music (object, music);
Packit Service c6b9b0
        }
Packit Service c6b9b0
    }
Packit Service c6b9b0
  else
Packit Service c6b9b0
    {
Packit Service c6b9b0
      if (music != NULL)
Packit Service c6b9b0
        goa_object_skeleton_set_music (object, NULL);
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  if (just_added)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      goa_account_set_music_disabled (account, !music_enabled);
Packit Service c6b9b0
Packit Service c6b9b0
      g_signal_connect (account,
Packit Service c6b9b0
                        "notify::music-disabled",
Packit Service c6b9b0
                        G_CALLBACK (goa_util_account_notify_property_cb),
Packit Service c6b9b0
                        (gpointer) "MusicEnabled");
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  ret = TRUE;
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  g_clear_object (&music);
Packit Service c6b9b0
  g_clear_object (&account);
Packit Service c6b9b0
  return ret;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static gboolean
Packit Service c6b9b0
lastfm_login_sync (GoaProvider                  *provider,
Packit Service c6b9b0
                   const gchar                  *username,
Packit Service c6b9b0
                   const gchar                  *password,
Packit Service c6b9b0
                   GError                       **error)
Packit Service c6b9b0
{
Packit Service c6b9b0
  JsonParser *parser;
Packit Service c6b9b0
  JsonObject *json_obj;
Packit Service c6b9b0
  JsonObject *session_obj;
Packit Service c6b9b0
  JsonNode *root;
Packit Service c6b9b0
  RestProxyCall *call;
Packit Service c6b9b0
  const gchar *payload;
Packit Service c6b9b0
  gchar *sig;
Packit Service c6b9b0
  gchar *sig_md5;
Packit Service c6b9b0
  gboolean ret;
Packit Service c6b9b0
Packit Service c6b9b0
  call = NULL;
Packit Service c6b9b0
  parser = NULL;
Packit Service c6b9b0
  ret = FALSE;
Packit Service c6b9b0
Packit Service c6b9b0
  sig = g_strdup_printf ("api_key%s"
Packit Service c6b9b0
                         "methodauth.getMobileSession"
Packit Service c6b9b0
                         "password%s"
Packit Service c6b9b0
                         "username%s"
Packit Service c6b9b0
                         "%s",
Packit Service c6b9b0
                         GOA_LASTFM_CLIENT_ID,
Packit Service c6b9b0
                         password,
Packit Service c6b9b0
                         username,
Packit Service c6b9b0
                         GOA_LASTFM_CLIENT_SECRET);
Packit Service c6b9b0
  sig_md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, sig, -1);
Packit Service c6b9b0
Packit Service c6b9b0
  call = rest_proxy_new_call (goa_rest_proxy_new (get_request_uri (provider), FALSE));
Packit Service c6b9b0
Packit Service c6b9b0
  rest_proxy_call_set_method (call, "POST");
Packit Service c6b9b0
  rest_proxy_call_add_header (call, "Content-Type", "application/x-www-form-urlencoded");
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "method", "auth.getMobileSession");
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "api_key", GOA_LASTFM_CLIENT_ID);
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "username", username);
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "password", password);
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "api_sig", sig_md5);
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "format", "json");
Packit Service c6b9b0
Packit Service c6b9b0
  if (!rest_proxy_call_sync (call, error))
Packit Service c6b9b0
    goto out;
Packit Service c6b9b0
Packit Service c6b9b0
  parser = json_parser_new ();
Packit Service c6b9b0
  payload = rest_proxy_call_get_payload (call);
Packit Service c6b9b0
  if (payload == NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_set_error (error, GOA_ERROR, GOA_ERROR_FAILED, _("Could not parse response"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  if (!json_parser_load_from_data (parser,
Packit Service c6b9b0
                                   payload,
Packit Service c6b9b0
                                   rest_proxy_call_get_payload_length (call),
Packit Service c6b9b0
                                   NULL))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_set_error (error, GOA_ERROR, GOA_ERROR_FAILED, _("Could not parse response"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  root = json_parser_get_root (parser);
Packit Service c6b9b0
  json_obj = json_node_get_object (root);
Packit Service c6b9b0
  if (!json_object_has_member (json_obj, "session"))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_warning ("Did not find session in JSON data");
Packit Service c6b9b0
      g_set_error (error, GOA_ERROR, GOA_ERROR_FAILED, _("Could not parse response"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  session_obj = json_node_get_object (json_object_get_member (json_obj, "session"));
Packit Service c6b9b0
  if (!json_object_has_member (session_obj, "name"))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_warning ("Did not find session.name in JSON data");
Packit Service c6b9b0
      g_set_error (error, GOA_ERROR, GOA_ERROR_FAILED, _("Could not parse response"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
  if (!json_object_has_member (session_obj, "key"))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_warning ("Did not find session.key in JSON data");
Packit Service c6b9b0
      g_set_error (error, GOA_ERROR, GOA_ERROR_FAILED, _("Could not parse response"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  ret = TRUE;
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  g_clear_object (&parser);
Packit Service c6b9b0
  g_clear_object (&call);
Packit Service c6b9b0
  return ret;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
/* ---------------------------------------------------------------------------------------------------- */
Packit Service c6b9b0
static gboolean
Packit Service c6b9b0
ensure_credentials_sync (GoaProvider         *provider,
Packit Service c6b9b0
                         GoaObject           *object,
Packit Service c6b9b0
                         gint                *out_expires_in,
Packit Service c6b9b0
                         GCancellable        *cancellable,
Packit Service c6b9b0
                         GError             **error)
Packit Service c6b9b0
{
Packit Service c6b9b0
  gchar *username = NULL;
Packit Service c6b9b0
  gchar *password = NULL;
Packit Service c6b9b0
  gboolean ret = FALSE;
Packit Service c6b9b0
Packit Service c6b9b0
  if (!goa_utils_get_credentials (provider, object, "password", &username, &password, cancellable, error))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      if (error != NULL)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          (*error)->domain = GOA_ERROR;
Packit Service c6b9b0
          (*error)->code = GOA_ERROR_NOT_AUTHORIZED;
Packit Service c6b9b0
        }
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  if (!lastfm_login_sync (provider, username, password, error))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      if (error != NULL)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          g_prefix_error (error,
Packit Service c6b9b0
                          /* Translators: the first %s is the username
Packit Service c6b9b0
                           * (eg., debarshi.ray@gmail.com or rishi), and the
Packit Service c6b9b0
                           * (%s, %d) is the error domain and code.
Packit Service c6b9b0
                           */
Packit Service c6b9b0
                          _("Invalid password with username “%s” (%s, %d): "),
Packit Service c6b9b0
                          username,
Packit Service c6b9b0
                          g_quark_to_string ((*error)->domain),
Packit Service c6b9b0
                          (*error)->code);
Packit Service c6b9b0
          (*error)->domain = GOA_ERROR;
Packit Service c6b9b0
          (*error)->code = GOA_ERROR_NOT_AUTHORIZED;
Packit Service c6b9b0
        }
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  if (out_expires_in != NULL)
Packit Service c6b9b0
    *out_expires_in = 0;
Packit Service c6b9b0
Packit Service c6b9b0
  ret = TRUE;
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  g_free (username);
Packit Service c6b9b0
  g_free (password);
Packit Service c6b9b0
  return ret;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
/* ---------------------------------------------------------------------------------------------------- */
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
add_entry (GtkWidget     *grid,
Packit Service c6b9b0
           gint           row,
Packit Service c6b9b0
           const gchar   *text,
Packit Service c6b9b0
           GtkWidget    **out_entry)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GtkStyleContext *context;
Packit Service c6b9b0
  GtkWidget *label;
Packit Service c6b9b0
  GtkWidget *entry;
Packit Service c6b9b0
Packit Service c6b9b0
  label = gtk_label_new_with_mnemonic (text);
Packit Service c6b9b0
  context = gtk_widget_get_style_context (label);
Packit Service c6b9b0
  gtk_style_context_add_class (context, GTK_STYLE_CLASS_DIM_LABEL);
Packit Service c6b9b0
  gtk_widget_set_halign (label, GTK_ALIGN_END);
Packit Service c6b9b0
  gtk_widget_set_hexpand (label, TRUE);
Packit Service c6b9b0
  gtk_grid_attach (GTK_GRID (grid), label, 0, row, 1, 1);
Packit Service c6b9b0
Packit Service c6b9b0
  entry = gtk_entry_new ();
Packit Service c6b9b0
  gtk_widget_set_hexpand (entry, TRUE);
Packit Service c6b9b0
  gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
Packit Service c6b9b0
  gtk_grid_attach (GTK_GRID (grid), entry, 1, row, 3, 1);
Packit Service c6b9b0
Packit Service c6b9b0
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
Packit Service c6b9b0
  if (out_entry != NULL)
Packit Service c6b9b0
    *out_entry = entry;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
/* ---------------------------------------------------------------------------------------------------- */
Packit Service c6b9b0
Packit Service c6b9b0
typedef struct
Packit Service c6b9b0
{
Packit Service c6b9b0
  GCancellable *cancellable;
Packit Service c6b9b0
Packit Service c6b9b0
  GtkDialog *dialog;
Packit Service c6b9b0
  GMainLoop *loop;
Packit Service c6b9b0
Packit Service c6b9b0
  GtkWidget *cluebar;
Packit Service c6b9b0
  GtkWidget *cluebar_label;
Packit Service c6b9b0
  GtkWidget *connect_button;
Packit Service c6b9b0
  GtkWidget *progress_grid;
Packit Service c6b9b0
Packit Service c6b9b0
  GtkWidget *username;
Packit Service c6b9b0
  GtkWidget *password;
Packit Service c6b9b0
Packit Service c6b9b0
  gchar *account_object_path;
Packit Service c6b9b0
  gchar *access_token;
Packit Service c6b9b0
Packit Service c6b9b0
  GError *error;
Packit Service c6b9b0
} AddAccountData;
Packit Service c6b9b0
Packit Service c6b9b0
/* ---------------------------------------------------------------------------------------------------- */
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_username_or_password_changed (GtkEditable *editable, gpointer user_data)
Packit Service c6b9b0
{
Packit Service c6b9b0
  AddAccountData *data = user_data;
Packit Service c6b9b0
  gboolean can_add;
Packit Service c6b9b0
  gchar *username;
Packit Service c6b9b0
  gchar *password;
Packit Service c6b9b0
Packit Service c6b9b0
  can_add = FALSE;
Packit Service c6b9b0
  username = NULL;
Packit Service c6b9b0
  password = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  username = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->username)));
Packit Service c6b9b0
  password = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->password)));
Packit Service c6b9b0
  if ((username == NULL) || (password == NULL))
Packit Service c6b9b0
    goto out;
Packit Service c6b9b0
Packit Service c6b9b0
  can_add = gtk_entry_get_text_length (GTK_ENTRY (data->username)) != 0
Packit Service c6b9b0
            && gtk_entry_get_text_length (GTK_ENTRY (data->password)) != 0;
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  gtk_dialog_set_response_sensitive (data->dialog, GTK_RESPONSE_OK, can_add);
Packit Service c6b9b0
  g_free (username);
Packit Service c6b9b0
  g_free (password);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
create_account_details_ui (GoaProvider    *provider,
Packit Service c6b9b0
                           GtkDialog      *dialog,
Packit Service c6b9b0
                           GtkBox         *vbox,
Packit Service c6b9b0
                           gboolean        new_account,
Packit Service c6b9b0
                           AddAccountData *data)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GtkWidget *grid0;
Packit Service c6b9b0
  GtkWidget *grid1;
Packit Service c6b9b0
  GtkWidget *label;
Packit Service c6b9b0
  GtkWidget *spinner;
Packit Service c6b9b0
  gint row;
Packit Service c6b9b0
  gint width;
Packit Service c6b9b0
Packit Service c6b9b0
  goa_utils_set_dialog_title (provider, dialog, new_account);
Packit Service c6b9b0
Packit Service c6b9b0
  grid0 = gtk_grid_new ();
Packit Service c6b9b0
  gtk_container_set_border_width (GTK_CONTAINER (grid0), 5);
Packit Service c6b9b0
  gtk_widget_set_margin_bottom (grid0, 6);
Packit Service c6b9b0
  gtk_orientable_set_orientation (GTK_ORIENTABLE (grid0), GTK_ORIENTATION_VERTICAL);
Packit Service c6b9b0
  gtk_grid_set_row_spacing (GTK_GRID (grid0), 12);
Packit Service c6b9b0
  gtk_container_add (GTK_CONTAINER (vbox), grid0);
Packit Service c6b9b0
Packit Service c6b9b0
  data->cluebar = gtk_info_bar_new ();
Packit Service c6b9b0
  gtk_info_bar_set_message_type (GTK_INFO_BAR (data->cluebar), GTK_MESSAGE_ERROR);
Packit Service c6b9b0
  gtk_widget_set_hexpand (data->cluebar, TRUE);
Packit Service c6b9b0
  gtk_widget_set_no_show_all (data->cluebar, TRUE);
Packit Service c6b9b0
  gtk_container_add (GTK_CONTAINER (grid0), data->cluebar);
Packit Service c6b9b0
Packit Service c6b9b0
  data->cluebar_label = gtk_label_new ("");
Packit Service c6b9b0
  gtk_label_set_line_wrap (GTK_LABEL (data->cluebar_label), TRUE);
Packit Service c6b9b0
  gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (data->cluebar))),
Packit Service c6b9b0
                     data->cluebar_label);
Packit Service c6b9b0
Packit Service c6b9b0
  grid1 = gtk_grid_new ();
Packit Service c6b9b0
  gtk_grid_set_column_spacing (GTK_GRID (grid1), 12);
Packit Service c6b9b0
  gtk_grid_set_row_spacing (GTK_GRID (grid1), 12);
Packit Service c6b9b0
  gtk_container_add (GTK_CONTAINER (grid0), grid1);
Packit Service c6b9b0
Packit Service c6b9b0
  row = 0;
Packit Service c6b9b0
  add_entry (grid1, row++, _("User_name"), &data->username);
Packit Service c6b9b0
  add_entry (grid1, row++, _("_Password"), &data->password);
Packit Service c6b9b0
  gtk_entry_set_visibility (GTK_ENTRY (data->password), FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  gtk_widget_grab_focus ((new_account) ? data->username : data->password);
Packit Service c6b9b0
Packit Service c6b9b0
  g_signal_connect (data->username, "changed", G_CALLBACK (on_username_or_password_changed), data);
Packit Service c6b9b0
  g_signal_connect (data->password, "changed", G_CALLBACK (on_username_or_password_changed), data);
Packit Service c6b9b0
Packit Service c6b9b0
  gtk_dialog_add_button (data->dialog, _("_Cancel"), GTK_RESPONSE_CANCEL);
Packit Service c6b9b0
  data->connect_button = gtk_dialog_add_button (data->dialog, _("C_onnect"), GTK_RESPONSE_OK);
Packit Service c6b9b0
  gtk_dialog_set_default_response (data->dialog, GTK_RESPONSE_OK);
Packit Service c6b9b0
  gtk_dialog_set_response_sensitive (data->dialog, GTK_RESPONSE_OK, FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  data->progress_grid = gtk_grid_new ();
Packit Service c6b9b0
  gtk_widget_set_no_show_all (data->progress_grid, TRUE);
Packit Service c6b9b0
  gtk_orientable_set_orientation (GTK_ORIENTABLE (data->progress_grid), GTK_ORIENTATION_HORIZONTAL);
Packit Service c6b9b0
  gtk_grid_set_column_spacing (GTK_GRID (data->progress_grid), 3);
Packit Service c6b9b0
  gtk_container_add (GTK_CONTAINER (grid0), data->progress_grid);
Packit Service c6b9b0
Packit Service c6b9b0
  spinner = gtk_spinner_new ();
Packit Service c6b9b0
  gtk_widget_set_size_request (spinner, 20, 20);
Packit Service c6b9b0
  gtk_widget_show (spinner);
Packit Service c6b9b0
  gtk_spinner_start (GTK_SPINNER (spinner));
Packit Service c6b9b0
  gtk_container_add (GTK_CONTAINER (data->progress_grid), spinner);
Packit Service c6b9b0
Packit Service c6b9b0
  label = gtk_label_new (_("Connecting…"));
Packit Service c6b9b0
  gtk_widget_show (label);
Packit Service c6b9b0
  gtk_container_add (GTK_CONTAINER (data->progress_grid), label);
Packit Service c6b9b0
Packit Service c6b9b0
  if (new_account)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      gtk_window_get_size (GTK_WINDOW (data->dialog), &width, NULL);
Packit Service c6b9b0
      gtk_window_set_default_size (GTK_WINDOW (data->dialog), width, -1);
Packit Service c6b9b0
    }
Packit Service c6b9b0
  else
Packit Service c6b9b0
    {
Packit Service c6b9b0
      GtkWindow *parent;
Packit Service c6b9b0
Packit Service c6b9b0
      /* Keep in sync with GoaPanelAddAccountDialog in
Packit Service c6b9b0
       * gnome-control-center.
Packit Service c6b9b0
       */
Packit Service c6b9b0
      parent = gtk_window_get_transient_for (GTK_WINDOW (data->dialog));
Packit Service c6b9b0
      if (parent != NULL)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          gtk_window_get_size (parent, &width, NULL);
Packit Service c6b9b0
          gtk_window_set_default_size (GTK_WINDOW (data->dialog), (gint) (0.5 * width), -1);
Packit Service c6b9b0
        }
Packit Service c6b9b0
    }
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
/* ---------------------------------------------------------------------------------------------------- */
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
add_account_cb (GoaManager *manager, GAsyncResult *res, gpointer user_data)
Packit Service c6b9b0
{
Packit Service c6b9b0
  AddAccountData *data = user_data;
Packit Service c6b9b0
  goa_manager_call_add_account_finish (manager,
Packit Service c6b9b0
                                       &data->account_object_path,
Packit Service c6b9b0
                                       res,
Packit Service c6b9b0
                                       &data->error);
Packit Service c6b9b0
  g_main_loop_quit (data->loop);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
check_cb (RestProxyCall *call,
Packit Service c6b9b0
          const GError *error,
Packit Service c6b9b0
          GObject *weak_object,
Packit Service c6b9b0
          gpointer user_data)
Packit Service c6b9b0
{
Packit Service c6b9b0
  AddAccountData *data = user_data;
Packit Service c6b9b0
  JsonNode *session;
Packit Service c6b9b0
  JsonParser *parser;
Packit Service c6b9b0
  JsonObject *json_obj;
Packit Service c6b9b0
  JsonObject *session_obj;
Packit Service c6b9b0
  const gchar *payload;
Packit Service c6b9b0
Packit Service c6b9b0
  parser = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  parser = json_parser_new ();
Packit Service c6b9b0
  payload = rest_proxy_call_get_payload (call);
Packit Service c6b9b0
Packit Service c6b9b0
  if (payload == NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_set_error (&data->error, GOA_ERROR, GOA_ERROR_FAILED, _("Could not parse response"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  if (!json_parser_load_from_data (parser,
Packit Service c6b9b0
                                   payload,
Packit Service c6b9b0
                                   rest_proxy_call_get_payload_length (call),
Packit Service c6b9b0
                                   &data->error))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_set_error (&data->error, GOA_ERROR, GOA_ERROR_FAILED, _("Could not parse response"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  json_obj = json_node_get_object (json_parser_get_root (parser));
Packit Service c6b9b0
  if (!json_object_has_member (json_obj, "session"))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_warning ("Did not find session in JSON data");
Packit Service c6b9b0
      g_set_error (&data->error, GOA_ERROR, GOA_ERROR_FAILED, _("Authentication failed"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  session = json_object_get_member (json_obj, "session");
Packit Service c6b9b0
  session_obj = json_node_get_object (session);
Packit Service c6b9b0
  if (!json_object_has_member (session_obj, "name"))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_warning ("Did not find session.name in JSON data");
Packit Service c6b9b0
      g_set_error (&data->error, GOA_ERROR, GOA_ERROR_FAILED, _("Could not parse response"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
  if (!json_object_has_member (session_obj, "key"))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_warning ("Did not find session.key in JSON data");
Packit Service c6b9b0
      g_set_error (&data->error, GOA_ERROR, GOA_ERROR_FAILED, _("Could not parse response"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  data->access_token = g_strdup (json_object_get_string_member (session_obj, "key"));
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  g_main_loop_quit (data->loop);
Packit Service c6b9b0
  gtk_widget_set_sensitive (data->connect_button, TRUE);
Packit Service c6b9b0
  gtk_widget_hide (data->progress_grid);
Packit Service c6b9b0
  g_clear_object (&parser);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data)
Packit Service c6b9b0
{
Packit Service c6b9b0
  AddAccountData *data = user_data;
Packit Service c6b9b0
Packit Service c6b9b0
  if (response_id == GTK_RESPONSE_CANCEL)
Packit Service c6b9b0
    g_cancellable_cancel (data->cancellable);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_rest_proxy_call_cancelled_cb (GCancellable *cancellable, RestProxyCall *call)
Packit Service c6b9b0
{
Packit Service c6b9b0
  rest_proxy_call_cancel (call);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
lastfm_login (GoaProvider                  *provider,
Packit Service c6b9b0
              const gchar                  *username,
Packit Service c6b9b0
              const gchar                  *password,
Packit Service c6b9b0
              GCancellable                 *cancellable,
Packit Service c6b9b0
              RestProxyCallAsyncCallback   callback,
Packit Service c6b9b0
              gpointer                     user_data)
Packit Service c6b9b0
{
Packit Service c6b9b0
  AddAccountData *data = user_data;
Packit Service c6b9b0
  RestProxyCall *call;
Packit Service c6b9b0
  gchar *sig;
Packit Service c6b9b0
  gchar *sig_md5;
Packit Service c6b9b0
Packit Service c6b9b0
  call = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  sig = g_strdup_printf ("api_key%s"
Packit Service c6b9b0
                         "methodauth.getMobileSession"
Packit Service c6b9b0
                         "password%s"
Packit Service c6b9b0
                         "username%s"
Packit Service c6b9b0
                         "%s",
Packit Service c6b9b0
                         GOA_LASTFM_CLIENT_ID,
Packit Service c6b9b0
                         password,
Packit Service c6b9b0
                         username,
Packit Service c6b9b0
                         GOA_LASTFM_CLIENT_SECRET);
Packit Service c6b9b0
  sig_md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, sig, -1);
Packit Service c6b9b0
Packit Service c6b9b0
  call = rest_proxy_new_call (goa_rest_proxy_new (get_request_uri (provider), FALSE));
Packit Service c6b9b0
Packit Service c6b9b0
  rest_proxy_call_set_method (call, "POST");
Packit Service c6b9b0
  rest_proxy_call_add_header (call, "Content-Type", "application/x-www-form-urlencoded");
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "method", "auth.getMobileSession");
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "api_key", GOA_LASTFM_CLIENT_ID);
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "username", username);
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "password", password);
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "api_sig", sig_md5);
Packit Service c6b9b0
  rest_proxy_call_add_param (call, "format", "json");
Packit Service c6b9b0
Packit Service c6b9b0
  rest_proxy_call_async (call, callback, NULL, data, &data->error);
Packit Service c6b9b0
Packit Service c6b9b0
  g_signal_connect (cancellable, "cancelled", G_CALLBACK (on_rest_proxy_call_cancelled_cb), call);
Packit Service c6b9b0
Packit Service c6b9b0
  g_free (sig_md5);
Packit Service c6b9b0
  g_free (sig);
Packit Service c6b9b0
  g_object_unref (call);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
/* ---------------------------------------------------------------------------------------------------- */
Packit Service c6b9b0
Packit Service c6b9b0
static GoaObject *
Packit Service c6b9b0
add_account (GoaProvider    *provider,
Packit Service c6b9b0
             GoaClient      *client,
Packit Service c6b9b0
             GtkDialog      *dialog,
Packit Service c6b9b0
             GtkBox         *vbox,
Packit Service c6b9b0
             GError        **error)
Packit Service c6b9b0
{
Packit Service c6b9b0
  AddAccountData data;
Packit Service c6b9b0
  GVariantBuilder credentials;
Packit Service c6b9b0
  GVariantBuilder details;
Packit Service c6b9b0
  GoaObject *ret;
Packit Service c6b9b0
  const gchar *password;
Packit Service c6b9b0
  const gchar *username;
Packit Service c6b9b0
  const gchar *provider_type;
Packit Service c6b9b0
  gint response;
Packit Service c6b9b0
Packit Service c6b9b0
  ret = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  memset (&data, 0, sizeof (AddAccountData));
Packit Service c6b9b0
  data.cancellable = g_cancellable_new ();
Packit Service c6b9b0
  data.loop = g_main_loop_new (NULL, FALSE);
Packit Service c6b9b0
  data.dialog = dialog;
Packit Service c6b9b0
  data.error = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  create_account_details_ui (provider, dialog, vbox, TRUE, &data);
Packit Service c6b9b0
  gtk_widget_show_all (GTK_WIDGET (vbox));
Packit Service c6b9b0
  g_signal_connect (dialog, "response", G_CALLBACK (dialog_response_cb), &data);
Packit Service c6b9b0
Packit Service c6b9b0
 login_again:
Packit Service c6b9b0
  response = gtk_dialog_run (dialog);
Packit Service c6b9b0
  if (response != GTK_RESPONSE_OK)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_set_error (&data.error, GOA_ERROR, GOA_ERROR_DIALOG_DISMISSED, _("Dialog was dismissed"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  username = gtk_entry_get_text (GTK_ENTRY (data.username));
Packit Service c6b9b0
  password = gtk_entry_get_text (GTK_ENTRY (data.password));
Packit Service c6b9b0
Packit Service c6b9b0
  /* See if there's already an account of this type with the
Packit Service c6b9b0
   * given identity
Packit Service c6b9b0
   */
Packit Service c6b9b0
  provider_type = goa_provider_get_provider_type (provider);
Packit Service c6b9b0
  if (!goa_utils_check_duplicate (client,
Packit Service c6b9b0
                                  username,
Packit Service c6b9b0
                                  username,
Packit Service c6b9b0
                                  provider_type,
Packit Service c6b9b0
                                  (GoaPeekInterfaceFunc) goa_object_peek_oauth2_based,
Packit Service c6b9b0
                                  &data.error))
Packit Service c6b9b0
    goto out;
Packit Service c6b9b0
Packit Service c6b9b0
  g_cancellable_reset (data.cancellable);
Packit Service c6b9b0
  lastfm_login (provider,
Packit Service c6b9b0
                username,
Packit Service c6b9b0
                password,
Packit Service c6b9b0
                data.cancellable,
Packit Service c6b9b0
                (RestProxyCallAsyncCallback) check_cb,
Packit Service c6b9b0
                &data);
Packit Service c6b9b0
Packit Service c6b9b0
  gtk_widget_set_sensitive (data.connect_button, FALSE);
Packit Service c6b9b0
  gtk_widget_show (data.progress_grid);
Packit Service c6b9b0
  g_main_loop_run (data.loop);
Packit Service c6b9b0
Packit Service c6b9b0
  if (g_cancellable_is_cancelled (data.cancellable))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_prefix_error (&data.error,
Packit Service c6b9b0
                      _("Dialog was dismissed (%s, %d): "),
Packit Service c6b9b0
                      g_quark_to_string (data.error->domain),
Packit Service c6b9b0
                      data.error->code);
Packit Service c6b9b0
      data.error->domain = GOA_ERROR;
Packit Service c6b9b0
      data.error->code = GOA_ERROR_DIALOG_DISMISSED;
Packit Service c6b9b0
      g_message ("%s", data.error->message);
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
  else if (data.error != NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      gchar *markup;
Packit Service c6b9b0
Packit Service c6b9b0
      gtk_button_set_label (GTK_BUTTON (data.connect_button), _("_Try Again"));
Packit Service c6b9b0
Packit Service c6b9b0
      markup = g_strdup_printf ("%s:\n%s", _("Error connecting to Last.fm"), data.error->message);
Packit Service c6b9b0
      g_clear_error (&data.error);
Packit Service c6b9b0
Packit Service c6b9b0
      gtk_label_set_markup (GTK_LABEL (data.cluebar_label), markup);
Packit Service c6b9b0
      g_free (markup);
Packit Service c6b9b0
Packit Service c6b9b0
      gtk_widget_set_no_show_all (data.cluebar, FALSE);
Packit Service c6b9b0
      gtk_widget_show_all (data.cluebar);
Packit Service c6b9b0
      goto login_again;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  gtk_widget_hide (GTK_WIDGET (dialog));
Packit Service c6b9b0
Packit Service c6b9b0
  g_variant_builder_init (&credentials, G_VARIANT_TYPE_VARDICT);
Packit Service c6b9b0
  g_variant_builder_add (&credentials, "{sv}", "password", g_variant_new_string (password));
Packit Service c6b9b0
  g_variant_builder_add (&credentials, "{sv}", "access_token", g_variant_new_string (data.access_token));
Packit Service c6b9b0
Packit Service c6b9b0
  g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
Packit Service c6b9b0
  g_variant_builder_add (&details, "{ss}", "MusicEnabled", "true");
Packit Service c6b9b0
Packit Service c6b9b0
  /* OK, everything is dandy, add the account */
Packit Service c6b9b0
  /* we want the GoaClient to update before this method returns (so it
Packit Service c6b9b0
   * can create a proxy for the new object) so run the mainloop while
Packit Service c6b9b0
   * waiting for this to complete
Packit Service c6b9b0
   */
Packit Service c6b9b0
  goa_manager_call_add_account (goa_client_get_manager (client),
Packit Service c6b9b0
                                goa_provider_get_provider_type (provider),
Packit Service c6b9b0
                                username,
Packit Service c6b9b0
                                username,
Packit Service c6b9b0
                                g_variant_builder_end (&credentials),
Packit Service c6b9b0
                                g_variant_builder_end (&details),
Packit Service c6b9b0
                                NULL, /* GCancellable* */
Packit Service c6b9b0
                                (GAsyncReadyCallback) add_account_cb,
Packit Service c6b9b0
                                &data);
Packit Service c6b9b0
  g_main_loop_run (data.loop);
Packit Service c6b9b0
  if (data.error != NULL)
Packit Service c6b9b0
    goto out;
Packit Service c6b9b0
Packit Service c6b9b0
  ret = GOA_OBJECT (g_dbus_object_manager_get_object (goa_client_get_object_manager (client),
Packit Service c6b9b0
                                                      data.account_object_path));
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  /* We might have an object even when data.error is set.
Packit Service c6b9b0
   * eg., if we failed to store the credentials in the keyring.
Packit Service c6b9b0
   */
Packit Service c6b9b0
  if (data.error != NULL)
Packit Service c6b9b0
    g_propagate_error (error, data.error);
Packit Service c6b9b0
  else
Packit Service c6b9b0
    g_assert (ret != NULL);
Packit Service c6b9b0
Packit Service c6b9b0
  g_signal_handlers_disconnect_by_func (dialog, dialog_response_cb, &data);
Packit Service c6b9b0
Packit Service c6b9b0
  g_free (data.access_token);
Packit Service c6b9b0
  g_free (data.account_object_path);
Packit Service c6b9b0
  g_clear_pointer (&data.loop, (GDestroyNotify) g_main_loop_unref);
Packit Service c6b9b0
  g_clear_object (&data.cancellable);
Packit Service c6b9b0
  return ret;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
/* ---------------------------------------------------------------------------------------------------- */
Packit Service c6b9b0
Packit Service c6b9b0
static gboolean
Packit Service c6b9b0
refresh_account (GoaProvider    *provider,
Packit Service c6b9b0
                 GoaClient      *client,
Packit Service c6b9b0
                 GoaObject      *object,
Packit Service c6b9b0
                 GtkWindow      *parent,
Packit Service c6b9b0
                 GError        **error)
Packit Service c6b9b0
{
Packit Service c6b9b0
  AddAccountData data;
Packit Service c6b9b0
  GVariantBuilder builder;
Packit Service c6b9b0
  GoaAccount *account;
Packit Service c6b9b0
  GtkWidget *dialog;
Packit Service c6b9b0
  GtkWidget *vbox;
Packit Service c6b9b0
  gboolean ret;
Packit Service c6b9b0
  const gchar *password;
Packit Service c6b9b0
  const gchar *username;
Packit Service c6b9b0
  gint response;
Packit Service c6b9b0
Packit Service c6b9b0
  g_return_val_if_fail (GOA_IS_LASTFM_PROVIDER (provider), FALSE);
Packit Service c6b9b0
  g_return_val_if_fail (GOA_IS_CLIENT (client), FALSE);
Packit Service c6b9b0
  g_return_val_if_fail (GOA_IS_OBJECT (object), FALSE);
Packit Service c6b9b0
  g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), FALSE);
Packit Service c6b9b0
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  ret = FALSE;
Packit Service c6b9b0
Packit Service c6b9b0
  dialog = gtk_dialog_new_with_buttons (NULL,
Packit Service c6b9b0
                                        parent,
Packit Service c6b9b0
                                        GTK_DIALOG_MODAL
Packit Service c6b9b0
                                        | GTK_DIALOG_DESTROY_WITH_PARENT
Packit Service c6b9b0
                                        | GTK_DIALOG_USE_HEADER_BAR,
Packit Service c6b9b0
                                        NULL,
Packit Service c6b9b0
                                        NULL);
Packit Service c6b9b0
  gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
Packit Service c6b9b0
  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
Packit Service c6b9b0
  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
Packit Service c6b9b0
  gtk_box_set_spacing (GTK_BOX (vbox), 12);
Packit Service c6b9b0
Packit Service c6b9b0
  memset (&data, 0, sizeof (AddAccountData));
Packit Service c6b9b0
  data.cancellable = g_cancellable_new ();
Packit Service c6b9b0
  data.loop = g_main_loop_new (NULL, FALSE);
Packit Service c6b9b0
  data.dialog = GTK_DIALOG (dialog);
Packit Service c6b9b0
  data.error = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  create_account_details_ui (provider, GTK_DIALOG (dialog), GTK_BOX (vbox), FALSE, &data);
Packit Service c6b9b0
Packit Service c6b9b0
  account = goa_object_peek_account (object);
Packit Service c6b9b0
  username = goa_account_get_identity (account);
Packit Service c6b9b0
  gtk_entry_set_text (GTK_ENTRY (data.username), username);
Packit Service c6b9b0
  gtk_editable_set_editable (GTK_EDITABLE (data.username), FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  gtk_widget_show_all (dialog);
Packit Service c6b9b0
  g_signal_connect (dialog, "response", G_CALLBACK (dialog_response_cb), &data);
Packit Service c6b9b0
Packit Service c6b9b0
 login_again:
Packit Service c6b9b0
  response = gtk_dialog_run (GTK_DIALOG (dialog));
Packit Service c6b9b0
  if (response != GTK_RESPONSE_OK)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_set_error (&data.error, GOA_ERROR, GOA_ERROR_DIALOG_DISMISSED, _("Dialog was dismissed"));
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  password = gtk_entry_get_text (GTK_ENTRY (data.password));
Packit Service c6b9b0
  g_cancellable_reset (data.cancellable);
Packit Service c6b9b0
  lastfm_login (provider,
Packit Service c6b9b0
                username,
Packit Service c6b9b0
                password,
Packit Service c6b9b0
                data.cancellable,
Packit Service c6b9b0
                (RestProxyCallAsyncCallback) check_cb,
Packit Service c6b9b0
                &data);
Packit Service c6b9b0
  gtk_widget_set_sensitive (data.connect_button, FALSE);
Packit Service c6b9b0
  gtk_widget_show (data.progress_grid);
Packit Service c6b9b0
  g_main_loop_run (data.loop);
Packit Service c6b9b0
Packit Service c6b9b0
  if (g_cancellable_is_cancelled (data.cancellable))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_prefix_error (&data.error,
Packit Service c6b9b0
                      _("Dialog was dismissed (%s, %d): "),
Packit Service c6b9b0
                      g_quark_to_string (data.error->domain),
Packit Service c6b9b0
                      data.error->code);
Packit Service c6b9b0
      data.error->domain = GOA_ERROR;
Packit Service c6b9b0
      data.error->code = GOA_ERROR_DIALOG_DISMISSED;
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
  else if (data.error != NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      gchar *markup;
Packit Service c6b9b0
Packit Service c6b9b0
      markup = g_strdup_printf ("%s:\n%s", _("Error connecting to Last.fm"), data.error->message);
Packit Service c6b9b0
      g_clear_error (&data.error);
Packit Service c6b9b0
Packit Service c6b9b0
      gtk_label_set_markup (GTK_LABEL (data.cluebar_label), markup);
Packit Service c6b9b0
      g_free (markup);
Packit Service c6b9b0
Packit Service c6b9b0
      gtk_button_set_label (GTK_BUTTON (data.connect_button), _("_Try Again"));
Packit Service c6b9b0
      gtk_widget_set_no_show_all (data.cluebar, FALSE);
Packit Service c6b9b0
      gtk_widget_show_all (data.cluebar);
Packit Service c6b9b0
      goto login_again;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  /* TODO: run in worker thread */
Packit Service c6b9b0
  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
Packit Service c6b9b0
  g_variant_builder_add (&builder, "{sv}", "password", g_variant_new_string (password));
Packit Service c6b9b0
  g_variant_builder_add (&builder, "{sv}", "access_token", g_variant_new_string (data.access_token));
Packit Service c6b9b0
Packit Service c6b9b0
  if (!goa_utils_store_credentials_for_object_sync (provider,
Packit Service c6b9b0
                                                    object,
Packit Service c6b9b0
                                                    g_variant_builder_end (&builder),
Packit Service c6b9b0
                                                    NULL, /* GCancellable */
Packit Service c6b9b0
                                                    &data.error))
Packit Service c6b9b0
    goto out;
Packit Service c6b9b0
Packit Service c6b9b0
  goa_account_call_ensure_credentials (account,
Packit Service c6b9b0
                                       NULL, /* GCancellable */
Packit Service c6b9b0
                                       NULL, NULL); /* callback, user_data */
Packit Service c6b9b0
Packit Service c6b9b0
  ret = TRUE;
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  if (data.error != NULL)
Packit Service c6b9b0
    g_propagate_error (error, data.error);
Packit Service c6b9b0
Packit Service c6b9b0
  gtk_widget_destroy (dialog);
Packit Service c6b9b0
  g_clear_pointer (&data.loop, (GDestroyNotify) g_main_loop_unref);
Packit Service c6b9b0
  g_free (data.access_token);
Packit Service c6b9b0
  g_clear_object (&data.cancellable);
Packit Service c6b9b0
  return ret;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
/* ---------------------------------------------------------------------------------------------------- */
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
goa_lastfm_provider_init (GoaLastfmProvider *provider)
Packit Service c6b9b0
{
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
goa_lastfm_provider_class_init (GoaLastfmProviderClass *klass)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaProviderClass *provider_class;
Packit Service c6b9b0
  GoaOAuth2ProviderClass *oauth2_class = GOA_OAUTH2_PROVIDER_CLASS (klass);
Packit Service c6b9b0
Packit Service c6b9b0
  provider_class = GOA_PROVIDER_CLASS (klass);
Packit Service c6b9b0
  provider_class->get_provider_type          = get_provider_type;
Packit Service c6b9b0
  provider_class->get_provider_name          = get_provider_name;
Packit Service c6b9b0
  provider_class->get_provider_group         = get_provider_group;
Packit Service c6b9b0
  provider_class->get_provider_features      = get_provider_features;
Packit Service c6b9b0
  provider_class->add_account                = add_account;
Packit Service c6b9b0
  provider_class->refresh_account            = refresh_account;
Packit Service c6b9b0
  provider_class->build_object               = build_object;
Packit Service c6b9b0
  provider_class->ensure_credentials_sync    = ensure_credentials_sync;
Packit Service c6b9b0
Packit Service c6b9b0
  oauth2_class->get_client_id              = get_client_id;
Packit Service c6b9b0
  oauth2_class->get_client_secret          = get_client_secret;
Packit Service c6b9b0
}