[gnome-software/wip/rancell/reviews] Use libsecret for storing Ubuntu One credentials
- From: William Hua <williamhua src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/wip/rancell/reviews] Use libsecret for storing Ubuntu One credentials
- Date: Tue, 23 Feb 2016 23:25:40 +0000 (UTC)
commit c3d9941dfb0a2c432ae34192831d8bf124a369b0
Author: William Hua <william hua canonical com>
Date: Mon Feb 22 18:06:09 2016 -0500
Use libsecret for storing Ubuntu One credentials
configure.ac | 1 +
src/plugins/Makefile.am | 9 +-
src/plugins/gs-plugin-ubuntu-reviews.c | 231 ++++++++++++++++++++++++++++++--
3 files changed, 227 insertions(+), 14 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 38ba2b8..61806f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,7 @@ PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.51.92)
PKG_CHECK_MODULES(GSETTINGS_DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.11.5)
PKG_CHECK_MODULES(GNOME_DESKTOP, gnome-desktop-3.0 >= 3.17.92)
PKG_CHECK_MODULES(OAUTH, oauth)
+PKG_CHECK_MODULES(LIBSECRET, libsecret-1)
AC_PATH_PROG(APPSTREAM_UTIL, [appstream-util], [unfound])
AC_ARG_ENABLE(man,
[AS_HELP_STRING([--enable-man],
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 1c61244..136cec7 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -14,6 +14,7 @@ AM_CPPFLAGS = \
$(LIMBA_CFLAGS) \
$(XDG_APP_CFLAGS) \
$(OAUTH_CFLAGS) \
+ $(LIBSECRET_CFLAGS) \
-DBINDIR=\"$(bindir)\" \
-DDATADIR=\"$(datadir)\" \
-DGS_MODULESETDIR=\"$(datadir)/gnome-software/modulesets.d\" \
@@ -165,7 +166,13 @@ libgs_plugin_hardcoded_blacklist_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
libgs_plugin_ubuntu_reviews_la_SOURCES = \
gs-plugin-ubuntu-reviews.c \
gs-ubuntu-login-dialog.c
-libgs_plugin_ubuntu_reviews_la_LIBADD = $(GS_PLUGIN_LIBS) $(SOUP_LIBS) $(JSON_GLIB_LIBS) $(OAUTH_LIBS)
$(SQLITE_LIBS)
+libgs_plugin_ubuntu_reviews_la_LIBADD = \
+ $(GS_PLUGIN_LIBS) \
+ $(SOUP_LIBS) \
+ $(JSON_GLIB_LIBS) \
+ $(OAUTH_LIBS) \
+ $(SQLITE_LIBS) \
+ $(LIBSECRET_LIBS)
libgs_plugin_ubuntu_reviews_la_LDFLAGS = -module -avoid-version
libgs_plugin_ubuntu_reviews_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
diff --git a/src/plugins/gs-plugin-ubuntu-reviews.c b/src/plugins/gs-plugin-ubuntu-reviews.c
index 64e3f81..3712182 100644
--- a/src/plugins/gs-plugin-ubuntu-reviews.c
+++ b/src/plugins/gs-plugin-ubuntu-reviews.c
@@ -27,6 +27,7 @@
#include <json-glib/json-glib.h>
#include <oauth.h>
#include <sqlite3.h>
+#include <libsecret/secret.h>
#include <gs-plugin.h>
#include <gs-utils.h>
@@ -34,6 +35,12 @@
#include "gs-ubuntu-login-dialog.h"
#include "gs-os-release.h"
+#define SCHEMA_NAME "com.ubuntu.UbuntuOne.GnomeSoftware"
+#define CONSUMER_KEY "consumer-key"
+#define CONSUMER_SECRET "consumer-secret"
+#define TOKEN_KEY "token-key"
+#define TOKEN_SECRET "token-secret"
+
struct GsPluginPrivate {
gchar *db_path;
sqlite3 *db;
@@ -842,6 +849,7 @@ typedef struct
GCond cond;
GMutex mutex;
+
gboolean done;
gboolean success;
gboolean remember;
@@ -886,40 +894,237 @@ show_login_dialog (gpointer user_data)
return G_SOURCE_REMOVE;
}
+typedef struct
+{
+ GsPlugin *plugin;
+
+ GCancellable *cancellable;
+ GCond cond;
+ GMutex mutex;
+
+ gint waiting;
+} SecretContext;
+
+static void
+lookup_consumer_key (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ SecretContext *context = user_data;
+
+ context->plugin->priv->consumer_key = secret_password_lookup_finish (result, NULL);
+
+ g_mutex_lock (&context->mutex);
+
+ if (context->plugin->priv->consumer_key != NULL)
+ context->waiting--;
+ else
+ context->waiting = 0;
+
+ g_cond_signal (&context->cond);
+ g_mutex_unlock (&context->mutex);
+}
+
+static void
+lookup_consumer_secret (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ SecretContext *context = user_data;
+
+ context->plugin->priv->consumer_secret = secret_password_lookup_finish (result, NULL);
+
+ g_mutex_lock (&context->mutex);
+
+ if (context->plugin->priv->consumer_secret != NULL)
+ context->waiting--;
+ else
+ context->waiting = 0;
+
+ g_cond_signal (&context->cond);
+ g_mutex_unlock (&context->mutex);
+}
+
+static void
+lookup_token_key (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ SecretContext *context = user_data;
+
+ context->plugin->priv->token_key = secret_password_lookup_finish (result, NULL);
+
+ g_mutex_lock (&context->mutex);
+
+ if (context->plugin->priv->token_key != NULL)
+ context->waiting--;
+ else
+ context->waiting = 0;
+
+ g_cond_signal (&context->cond);
+ g_mutex_unlock (&context->mutex);
+}
+
+static void
+lookup_token_secret (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ SecretContext *context = user_data;
+
+ context->plugin->priv->token_secret = secret_password_lookup_finish (result, NULL);
+
+ g_mutex_lock (&context->mutex);
+
+ if (context->plugin->priv->token_secret != NULL)
+ context->waiting--;
+ else
+ context->waiting = 0;
+
+ g_cond_signal (&context->cond);
+ g_mutex_unlock (&context->mutex);
+}
+
static gboolean
sign_into_ubuntu (GsPlugin *plugin,
GError **error)
{
+ static SecretSchema schema = {
+ SCHEMA_NAME,
+ SECRET_SCHEMA_NONE,
+ { { "key", SECRET_SCHEMA_ATTRIBUTE_STRING } }
+ };
+
GsPluginPrivate *priv = plugin->priv;
- LoginContext context = { 0 };
+ SecretContext secret_context = { 0 };
+ LoginContext login_context = { 0 };
+ /* Use current credentials if already available */
if (priv->consumer_key != NULL &&
priv->consumer_secret != NULL &&
priv->token_key != NULL &&
priv->token_secret != NULL)
return TRUE;
+ /* Otherwise start with a clean slate */
g_clear_pointer (&priv->token_secret, g_free);
g_clear_pointer (&priv->token_key, g_free);
g_clear_pointer (&priv->consumer_secret, g_free);
g_clear_pointer (&priv->consumer_key, g_free);
- context.plugin = plugin;
- context.error = error;
- g_cond_init (&context.cond);
- g_mutex_init (&context.mutex);
- g_mutex_lock (&context.mutex);
+ /* Use credentials from libsecret if available */
+ secret_context.plugin = plugin;
+ secret_context.waiting = 4;
+ secret_context.cancellable = g_cancellable_new ();
+ g_cond_init (&secret_context.cond);
+ g_mutex_init (&secret_context.mutex);
+ g_mutex_lock (&secret_context.mutex);
+
+ secret_password_lookup (&schema,
+ secret_context.cancellable,
+ lookup_consumer_key,
+ &secret_context,
+ "key", CONSUMER_KEY,
+ NULL);
+ secret_password_lookup (&schema,
+ secret_context.cancellable,
+ lookup_consumer_secret,
+ &secret_context,
+ "key", CONSUMER_SECRET,
+ NULL);
+ secret_password_lookup (&schema,
+ secret_context.cancellable,
+ lookup_token_key,
+ &secret_context,
+ "key", TOKEN_KEY,
+ NULL);
+ secret_password_lookup (&schema,
+ secret_context.cancellable,
+ lookup_token_secret,
+ &secret_context,
+ "key", TOKEN_SECRET,
+ NULL);
+
+ while (secret_context.waiting > 0)
+ g_cond_wait (&secret_context.cond, &secret_context.mutex);
+
+ g_mutex_unlock (&secret_context.mutex);
+ g_mutex_clear (&secret_context.mutex);
+ g_cond_clear (&secret_context.cond);
+ g_cancellable_cancel (secret_context.cancellable);
+ g_clear_object (&secret_context.cancellable);
- gdk_threads_add_idle (show_login_dialog, &context);
+ if (priv->consumer_key != NULL &&
+ priv->consumer_secret != NULL &&
+ priv->token_key != NULL &&
+ priv->token_secret != NULL)
+ return TRUE;
- while (!context.done)
- g_cond_wait (&context.cond, &context.mutex);
+ /* Otherwise start with a clean slate */
+ g_clear_pointer (&priv->token_secret, g_free);
+ g_clear_pointer (&priv->token_key, g_free);
+ g_clear_pointer (&priv->consumer_secret, g_free);
+ g_clear_pointer (&priv->consumer_key, g_free);
- g_mutex_unlock (&context.mutex);
- g_mutex_clear (&context.mutex);
- g_cond_clear (&context.cond);
+ /* Pop up a login dialog */
+ login_context.plugin = plugin;
+ login_context.error = error;
+ g_cond_init (&login_context.cond);
+ g_mutex_init (&login_context.mutex);
+ g_mutex_lock (&login_context.mutex);
+
+ gdk_threads_add_idle (show_login_dialog, &login_context);
+
+ while (!login_context.done)
+ g_cond_wait (&login_context.cond, &login_context.mutex);
+
+ g_mutex_unlock (&login_context.mutex);
+ g_mutex_clear (&login_context.mutex);
+ g_cond_clear (&login_context.cond);
+
+ if (login_context.remember) {
+ secret_password_store (&schema,
+ NULL,
+ SCHEMA_NAME,
+ priv->consumer_key,
+ NULL,
+ NULL,
+ NULL,
+ "key", CONSUMER_KEY,
+ NULL);
+
+ secret_password_store (&schema,
+ NULL,
+ SCHEMA_NAME,
+ priv->consumer_secret,
+ NULL,
+ NULL,
+ NULL,
+ "key", CONSUMER_SECRET,
+ NULL);
+
+ secret_password_store (&schema,
+ NULL,
+ SCHEMA_NAME,
+ priv->token_key,
+ NULL,
+ NULL,
+ NULL,
+ "key", TOKEN_KEY,
+ NULL);
+
+ secret_password_store (&schema,
+ NULL,
+ SCHEMA_NAME,
+ priv->token_secret,
+ NULL,
+ NULL,
+ NULL,
+ "key", TOKEN_SECRET,
+ NULL);
+ }
- return context.success;
+ return login_context.success;
}
gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]