[gnome-software/wip/rancell/snap-auth-3-20: 57/57] Replace UbuntuOne dialog and use GsAuth



commit 30c795f4c1bf939495a43b87c802f91f7db2c22d
Author: Robert Ancell <robert ancell canonical com>
Date:   Fri Sep 15 17:04:23 2017 +1200

    Replace UbuntuOne dialog and use GsAuth

 po/POTFILES.in                         |    2 -
 src/gnome-software.gresource.xml       |    2 -
 src/plugins/Makefile.am                |   26 +-
 src/plugins/gs-plugin-snap.c           |  150 ++++++++-
 src/plugins/gs-plugin-ubuntu-reviews.c |  103 ++----
 src/plugins/gs-plugin-ubuntuone.c      |  266 +++++++++++++++
 src/plugins/gs-snapd.c                 |  122 ++-----
 src/plugins/gs-snapd.h                 |   32 ++-
 src/plugins/gs-ubuntuone-dialog.c      |  563 --------------------------------
 src/plugins/gs-ubuntuone-dialog.h      |   45 ---
 src/plugins/gs-ubuntuone-dialog.ui     |  386 ----------------------
 src/plugins/gs-ubuntuone.c             |  419 ------------------------
 src/plugins/gs-ubuntuone.h             |   51 ---
 src/plugins/ubuntu-one.png             |  Bin 2540 -> 0 bytes
 14 files changed, 511 insertions(+), 1656 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 91c990a..313957f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -59,8 +59,6 @@ src/gs-upgrade-banner.c
 src/gs-utils.c
 [type: gettext/glade]src/gs-menus.ui
 src/org.gnome.Software.desktop.in
-src/plugins/gs-ubuntuone-dialog.c
-[type: gettext/glade]src/plugins/gs-ubuntuone-dialog.ui
 src/plugins/gs-plugin-snap.c
 src/plugins/menu-spec-common.c
 [type: gettext/glade]src/gs-popular-tile.ui
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index dd289a2..73600ae 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -33,7 +33,5 @@
   <file preprocess="xml-stripblanks">org.freedesktop.PackageKit.xml</file>
   <file>gtk-style.css</file>
   <file>gtk-style-hc.css</file>
-  <file>plugins/ubuntu-one.png</file>
-  <file preprocess="xml-stripblanks">plugins/gs-ubuntuone-dialog.ui</file>
  </gresource>
 </gresources>
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 2b71caa..b9a8861 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -41,7 +41,8 @@ plugin_LTLIBRARIES =                                  \
        libgs_plugin_provenance.la                      \
        libgs_plugin_fedora_tagger_usage.la             \
        libgs_plugin_epiphany.la                        \
-       libgs_plugin_icons.la
+       libgs_plugin_icons.la                           \
+       libgs_plugin_ubuntuone.la
 
 if HAVE_APT
 plugin_LTLIBRARIES +=                                  \
@@ -211,13 +212,7 @@ libgs_plugin_hardcoded_blacklist_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 
 if HAVE_UBUNTU_REVIEWS
 libgs_plugin_ubuntu_reviews_la_SOURCES =               \
-       gs-plugin-ubuntu-reviews.c                      \
-       gs-ubuntuone.h                                  \
-       gs-ubuntuone.c                                  \
-       gs-ubuntuone-dialog.h                           \
-       gs-ubuntuone-dialog.c                           \
-       gs-snapd.h                                      \
-       gs-snapd.c
+       gs-plugin-ubuntu-reviews.c
 libgs_plugin_ubuntu_reviews_la_LIBADD =                        \
        $(GS_PLUGIN_LIBS)                               \
        $(SOUP_LIBS)                                    \
@@ -301,10 +296,6 @@ libgs_plugin_packagekit_proxy_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 if HAVE_SNAP
 libgs_plugin_snap_la_SOURCES =                         \
        gs-plugin-snap.c                                \
-       gs-ubuntuone.h                                  \
-       gs-ubuntuone.c                                  \
-       gs-ubuntuone-dialog.h                           \
-       gs-ubuntuone-dialog.c                           \
        gs-snapd.h                                      \
        gs-snapd.c
 libgs_plugin_snap_la_LIBADD =                          \
@@ -317,6 +308,15 @@ libgs_plugin_snap_la_LDFLAGS = -module -avoid-version
 libgs_plugin_snap_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS) -DUSE_SNAPD
 endif
 
+libgs_plugin_ubuntuone_la_SOURCES =                    \
+       gs-plugin-ubuntuone.c
+libgs_plugin_ubuntuone_la_LIBADD =                     \
+       $(GS_PLUGIN_LIBS)                               \
+       $(SOUP_LIBS)                                    \
+       $(JSON_GLIB_LIBS)
+libgs_plugin_ubuntuone_la_LDFLAGS = -module -avoid-version
+libgs_plugin_ubuntuone_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
+
 check_PROGRAMS =                                               \
        gs-self-test
 
@@ -333,6 +333,6 @@ gs_self_test_CFLAGS = $(WARN_CFLAGS)
 
 TESTS = gs-self-test
 
-EXTRA_DIST = moduleset-test.xml gs-ubuntuone-dialog.h gs-ubuntuone-dialog.ui ubuntu-one.png 
com.canonical.Unity.Launcher.xml
+EXTRA_DIST = moduleset-test.xml com.canonical.Unity.Launcher.xml
 
 -include $(top_srcdir)/git.mk
diff --git a/src/plugins/gs-plugin-snap.c b/src/plugins/gs-plugin-snap.c
index bf7bc29..4b4048b 100644
--- a/src/plugins/gs-plugin-snap.c
+++ b/src/plugins/gs-plugin-snap.c
@@ -24,11 +24,12 @@
 
 #include <glib/gi18n.h>
 #include <json-glib/json-glib.h>
+#include <snapd-glib/snapd-glib.h>
 #include "gs-snapd.h"
-#include "gs-ubuntuone.h"
 
 struct GsPluginPrivate {
        gchar           *store_name;
+       GsAuth          *auth;
        GHashTable      *store_snaps;
 };
 
@@ -74,6 +75,33 @@ gs_plugin_initialize (GsPlugin *plugin)
                                                           g_free, (GDestroyNotify) json_object_unref);
 }
 
+static void
+get_macaroon (GsPlugin *plugin, gchar **macaroon, gchar ***discharges)
+{
+       GsAuth *auth;
+       const gchar *serialized_macaroon;
+       g_autoptr(GVariant) macaroon_variant = NULL;
+       g_autoptr (GError) error_local = NULL;
+
+       *macaroon = NULL;
+       *discharges = NULL;
+
+       auth = gs_plugin_get_auth_by_id (plugin, "snapd");
+       if (auth == NULL)
+               return;
+       serialized_macaroon = gs_auth_get_metadata_item (auth, "macaroon");
+       if (serialized_macaroon == NULL)
+               return;
+       macaroon_variant = g_variant_parse (G_VARIANT_TYPE ("(sas)"),
+                                           serialized_macaroon,
+                                           NULL,
+                                           NULL,
+                                           NULL);
+       if (macaroon_variant == NULL)
+               return;
+       g_variant_get (macaroon_variant, "(s^as)", macaroon, discharges);
+ }
+
 static gboolean
 gs_plugin_snap_set_app_pixbuf_from_data (GsApp *app, const gchar *buf, gsize count, GError **error)
 {
@@ -105,10 +133,13 @@ gs_plugin_snap_set_app_pixbuf_from_data (GsApp *app, const gchar *buf, gsize cou
 static JsonArray *
 find_snaps (GsPlugin *plugin, const gchar *section, gboolean match_name, const gchar *query, GCancellable 
*cancellable, GError **error)
 {
+       g_autofree gchar *macaroon = NULL;
+       g_auto(GStrv) discharges = NULL;
        g_autoptr(JsonArray) snaps = NULL;
        guint i;
 
-       snaps = gs_snapd_find (section, match_name, query, cancellable, error);
+       get_macaroon (plugin, &macaroon, &discharges);
+       snaps = gs_snapd_find (macaroon, discharges, section, match_name, query, cancellable, error);
        if (snaps == NULL)
                return NULL;
 
@@ -192,6 +223,7 @@ void
 gs_plugin_destroy (GsPlugin *plugin)
 {
        g_free (plugin->priv->store_name);
+       g_object_unref (plugin->priv->auth);
        g_hash_table_unref (plugin->priv->store_snaps);
 }
 
@@ -326,10 +358,13 @@ gs_plugin_add_installed (GsPlugin *plugin,
                         GCancellable *cancellable,
                         GError **error)
 {
+       g_autofree gchar *macaroon = NULL;
+       g_auto(GStrv) discharges = NULL;
        g_autoptr(JsonArray) snaps = NULL;
        guint i;
 
-       snaps = gs_snapd_list (cancellable, error);
+       get_macaroon (plugin, &macaroon, &discharges);
+       snaps = gs_snapd_list (macaroon, discharges, cancellable, error);
        if (snaps == NULL)
                return FALSE;
 
@@ -384,10 +419,13 @@ load_icon (GsPlugin *plugin, GsApp *app, const gchar *icon_url, GCancellable *ca
 
        /* icon is optional, either loaded from snapd or from a URL */
        if (g_str_has_prefix (icon_url, "/")) {
+               g_autofree gchar *macaroon = NULL;
+               g_auto(GStrv) discharges = NULL;
                g_autofree gchar *icon_data = NULL;
                gsize icon_data_length;
 
-               icon_data = gs_snapd_get_resource (icon_url, &icon_data_length, cancellable, error);
+               get_macaroon (plugin, &macaroon, &discharges);
+               icon_data = gs_snapd_get_resource (macaroon, discharges, icon_url, &icon_data_length, 
cancellable, error);
                if (icon_data == NULL)
                        return FALSE;
 
@@ -458,6 +496,8 @@ gs_plugin_refine_app (GsPlugin *plugin,
                      GCancellable *cancellable,
                      GError **error)
 {
+       g_autofree gchar *macaroon = NULL;
+       g_auto(GStrv) discharges = NULL;
        const gchar *id, *icon_url = NULL;
        g_autoptr(JsonObject) local_snap = NULL;
        g_autoptr(JsonObject) store_snap = NULL;
@@ -466,12 +506,14 @@ gs_plugin_refine_app (GsPlugin *plugin,
        if (g_strcmp0 (gs_app_get_management_plugin (app), "snap") != 0)
                return TRUE;
 
+       get_macaroon (plugin, &macaroon, &discharges);
+
        id = gs_app_get_id (app);
        if (id == NULL)
                id = gs_app_get_source_default (app);
 
        /* get information from installed snaps */
-       local_snap = gs_snapd_list_one (id, cancellable, NULL);
+       local_snap = gs_snapd_list_one (macaroon, discharges, id, cancellable, NULL);
        if (local_snap != NULL) {
                JsonArray *apps;
                g_autoptr(GDateTime) install_date = NULL;
@@ -615,16 +657,20 @@ gs_plugin_app_install (GsPlugin *plugin,
                       GCancellable *cancellable,
                       GError **error)
 {
+       g_autofree gchar *macaroon = NULL;
+       g_auto(GStrv) discharges = NULL;
        ProgressData data;
 
        /* We can only install apps we know of */
        if (g_strcmp0 (gs_app_get_management_plugin (app), "snap") != 0)
                return TRUE;
 
+       get_macaroon (plugin, &macaroon, &discharges);
+
        gs_app_set_state (app, AS_APP_STATE_INSTALLING);
        data.plugin = plugin;
        data.app = app;
-       if (!gs_snapd_install (gs_app_get_id (app), progress_cb, &data, cancellable, error)) {
+       if (!gs_snapd_install (macaroon, discharges, gs_app_get_id (app), progress_cb, &data, cancellable, 
error)) {
                gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
                return FALSE;
        }
@@ -643,7 +689,7 @@ is_graphical (GsApp *app, GCancellable *cancellable)
        guint i;
        g_autoptr(GError) error = NULL;
 
-       result = gs_snapd_get_interfaces (cancellable, &error);
+       result = gs_snapd_get_interfaces (NULL, NULL, cancellable, &error);
        if (result == NULL) {
                g_warning ("Failed to check interfaces: %s", error->message);
                return FALSE;
@@ -708,19 +754,107 @@ gs_plugin_app_remove (GsPlugin *plugin,
                      GCancellable *cancellable,
                      GError **error)
 {
+       g_autofree gchar *macaroon = NULL;
+       g_auto(GStrv) discharges = NULL;
        ProgressData data;
 
        /* We can only remove apps we know of */
        if (g_strcmp0 (gs_app_get_management_plugin (app), "snap") != 0)
                return TRUE;
 
+       get_macaroon (plugin, &macaroon, &discharges);
+
        gs_app_set_state (app, AS_APP_STATE_REMOVING);
        data.plugin = plugin;
        data.app = app;
-       if (!gs_snapd_remove (gs_app_get_id (app), progress_cb, &data, cancellable, error)) {
+       if (!gs_snapd_remove (macaroon, discharges, gs_app_get_id (app), progress_cb, &data, cancellable, 
error)) {
                gs_app_set_state (app, AS_APP_STATE_INSTALLED);
                return FALSE;
        }
        gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
        return TRUE;
 }
+
+gboolean
+gs_plugin_auth_login (GsPlugin *plugin, GsAuth *auth,
+                     GCancellable *cancellable, GError **error)
+{
+       g_autoptr(SnapdAuthData) auth_data = NULL;
+       g_autoptr(GVariant) macaroon_variant = NULL;
+       g_autofree gchar *serialized_macaroon = NULL;
+       g_autoptr(GError) local_error = NULL;
+
+       if (auth != plugin->priv->auth)
+               return TRUE;
+
+       auth_data = snapd_login_sync (gs_auth_get_username (auth), gs_auth_get_password (auth), 
gs_auth_get_pin (auth), NULL, &local_error);
+       if (auth_data == NULL) {
+               if (g_error_matches (local_error, SNAPD_ERROR, SNAPD_ERROR_TWO_FACTOR_REQUIRED)) {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_PIN_REQUIRED,
+                                            local_error->message);
+               } else if (g_error_matches (local_error, SNAPD_ERROR, SNAPD_ERROR_AUTH_DATA_INVALID) ||
+                          g_error_matches (local_error, SNAPD_ERROR, SNAPD_ERROR_TWO_FACTOR_INVALID)) {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_AUTH_INVALID,
+                                            local_error->message);
+               } else {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_NOT_SUPPORTED,
+                                            local_error->message);
+               }
+               return FALSE;
+       }
+
+       macaroon_variant = g_variant_new ("(s^as)",
+                                         snapd_auth_data_get_macaroon (auth_data),
+                                         snapd_auth_data_get_discharges (auth_data));
+       serialized_macaroon = g_variant_print (macaroon_variant, FALSE);
+       gs_auth_add_metadata (auth, "macaroon", serialized_macaroon);
+
+       /* store */
+       if (!gs_auth_store_save (auth,
+                                GS_AUTH_STORE_FLAG_USERNAME |
+                                GS_AUTH_STORE_FLAG_METADATA,
+                                cancellable, error))
+               return FALSE;
+
+       gs_auth_add_flags (plugin->priv->auth, GS_AUTH_FLAG_VALID);
+
+       return TRUE;
+}
+
+gboolean
+gs_plugin_auth_lost_password (GsPlugin *plugin, GsAuth *auth,
+                             GCancellable *cancellable, GError **error)
+{
+       if (auth != plugin->priv->auth)
+               return TRUE;
+
+       // FIXME: snapd might not be using Ubuntu One accounts
+       // https://bugs.launchpad.net/bugs/1598667
+       g_set_error_literal (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_AUTH_INVALID,
+                            "do online using @https://login.ubuntu.com/+forgot_password";);
+       return FALSE;
+}
+
+gboolean
+gs_plugin_auth_register (GsPlugin *plugin, GsAuth *auth,
+                        GCancellable *cancellable, GError **error)
+{
+       if (auth != plugin->priv->auth)
+               return TRUE;
+
+       // FIXME: snapd might not be using Ubuntu One accounts
+       // https://bugs.launchpad.net/bugs/1598667
+       g_set_error_literal (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_AUTH_INVALID,
+                            "do online using @https://login.ubuntu.com/+login";);
+       return FALSE;
+}
diff --git a/src/plugins/gs-plugin-ubuntu-reviews.c b/src/plugins/gs-plugin-ubuntu-reviews.c
index c3aee59..884c4c4 100644
--- a/src/plugins/gs-plugin-ubuntu-reviews.c
+++ b/src/plugins/gs-plugin-ubuntu-reviews.c
@@ -31,17 +31,12 @@
 #include <gs-plugin.h>
 #include <gs-utils.h>
 
-#include "gs-ubuntuone.h"
 #include "gs-os-release.h"
 
 struct GsPluginPrivate {
        gchar           *db_path;
        sqlite3         *db;
        gsize            db_loaded;
-       gchar           *consumer_key;
-       gchar           *consumer_secret;
-       gchar           *token_key;
-       gchar           *token_secret;
 };
 
 typedef struct {
@@ -112,10 +107,6 @@ gs_plugin_destroy (GsPlugin *plugin)
 {
        GsPluginPrivate *priv = plugin->priv;
 
-       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_clear_pointer (&priv->db, sqlite3_close);
        g_free (priv->db_path);
 }
@@ -380,12 +371,25 @@ parse_review_entries (GsPlugin *plugin, JsonParser *parser, GError **error)
 
 static void
 sign_message (SoupMessage *message, OAuthMethod method,
-             const gchar *consumer_key, const gchar *consumer_secret,
-             const gchar *token_key, const gchar *token_secret)
+             GsAuth *auth)
 {
        g_autofree gchar *url = NULL, *oauth_authorization_parameters = NULL, *authorization_text = NULL;
        gchar **url_parameters = NULL;
        int url_parameters_length;
+       const gchar *consumer_key;
+       const gchar *consumer_secret;
+       const gchar *token_key;
+       const gchar *token_secret;
+
+       if (auth == NULL)
+               return;
+
+       consumer_key = gs_auth_get_metadata_item (auth, "consumer-key");
+       consumer_secret = gs_auth_get_metadata_item (auth, "consumer-secret");
+       token_key = gs_auth_get_metadata_item (auth, "token-key");
+       token_secret = gs_auth_get_metadata_item (auth, "token-secret");
+       if (consumer_key == NULL || consumer_secret == NULL || token_key == NULL || token_secret == NULL)
+               return;
 
        url = soup_uri_to_string (soup_message_get_uri (message), FALSE);
 
@@ -405,7 +409,6 @@ sign_message (SoupMessage *message, OAuthMethod method,
 static gboolean
 send_review_request (GsPlugin *plugin, const gchar *method, const gchar *path, JsonBuilder *request, 
gboolean do_sign, JsonParser **result, GError **error)
 {
-       GsPluginPrivate *priv = plugin->priv;
        g_autofree gchar *uri = NULL;
        g_autoptr(SoupMessage) msg = NULL;
        guint status_code;
@@ -428,18 +431,15 @@ send_review_request (GsPlugin *plugin, const gchar *method, const gchar *path, J
        if (do_sign)
                sign_message (msg,
                              OA_PLAINTEXT,
-                             priv->consumer_key,
-                             priv->consumer_secret,
-                             priv->token_key,
-                             priv->token_secret);
+                             gs_plugin_get_auth_by_id (plugin, "ubuntuone"));
 
        status_code = soup_session_send_message (plugin->soup_session, msg);
-       if (status_code != SOUP_STATUS_OK) {
-               g_set_error (error,
-                            GS_PLUGIN_ERROR,
-                            GS_PLUGIN_ERROR_FAILED,
-                            "Got status code %s from reviews.ubuntu.com",
-                            soup_status_get_phrase (status_code));
+
+       if (status_code == SOUP_STATUS_UNAUTHORIZED) {
+               g_set_error_literal (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_AUTH_REQUIRED,
+                                    "Requires authentication with @ubuntuone");
                return FALSE;
        }
 
@@ -621,9 +621,8 @@ parse_date_time (const gchar *text)
 }
 
 static GsReview *
-parse_review (GsPlugin *plugin, JsonNode *node)
+parse_review (GsPlugin *plugin, const gchar *our_username, JsonNode *node)
 {
-       GsPluginPrivate *priv = plugin->priv;
        GsReview *review;
        JsonObject *object;
        gint64 star_rating;
@@ -635,7 +634,7 @@ parse_review (GsPlugin *plugin, JsonNode *node)
        object = json_node_get_object (node);
 
        review = gs_review_new ();
-       if (g_strcmp0 (priv->consumer_key, json_object_get_string_member (object, "reviewer_username")) == 0)
+       if (g_strcmp0 (our_username, json_object_get_string_member (object, "reviewer_username")) == 0)
                gs_review_add_flags (review, GS_REVIEW_FLAG_SELF);
        gs_review_set_reviewer (review, json_object_get_string_member (object, "reviewer_displayname"));
        gs_review_set_summary (review, json_object_get_string_member (object, "summary"));
@@ -654,9 +653,15 @@ parse_review (GsPlugin *plugin, JsonNode *node)
 static gboolean
 parse_reviews (GsPlugin *plugin, JsonParser *parser, GsApp *app, GError **error)
 {
+       GsAuth *auth;
        JsonArray *array;
+       const gchar *consumer_key = NULL;
        guint i;
 
+       auth = gs_plugin_get_auth_by_id (plugin, "ubuntuone");
+       if (auth != NULL)
+               consumer_key = gs_auth_get_metadata_item (auth, "consumer-key");
+
        if (!JSON_NODE_HOLDS_ARRAY (json_parser_get_root (parser)))
                return FALSE;
        array = json_node_get_array (json_parser_get_root (parser));
@@ -664,7 +669,7 @@ parse_reviews (GsPlugin *plugin, JsonParser *parser, GsApp *app, GError **error)
                g_autoptr(GsReview) review = NULL;
 
                /* Read in from JSON... (skip bad entries) */
-               review = parse_review (plugin, json_array_get_element (array, i));
+               review = parse_review (plugin, consumer_key, json_array_get_element (array, i));
                if (review != NULL)
                        gs_app_add_review (app, review);
        }
@@ -754,45 +759,11 @@ refine_rating (GsPlugin *plugin, GsApp *app, GError **error)
 }
 
 static gboolean
-get_ubuntuone_credentials (GsPlugin  *plugin,
-                          gboolean   required,
-                          GError   **error)
-{
-       GsPluginPrivate *priv = plugin->priv;
-
-       /* 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);
-
-       /* Use credentials if we have them */
-       if (gs_ubuntuone_get_credentials (&priv->consumer_key, &priv->consumer_secret, &priv->token_key, 
&priv->token_secret))
-               return TRUE;
-
-       /* Otherwise log in to get them */
-       if (required)
-               return gs_ubuntuone_sign_in (&priv->consumer_key, &priv->consumer_secret, &priv->token_key, 
&priv->token_secret, error);
-       else
-               return TRUE;
-}
-
-static gboolean
 refine_reviews (GsPlugin *plugin, GsApp *app, GError **error)
 {
        GPtrArray *sources;
        guint i, j;
 
-       if (!get_ubuntuone_credentials (plugin, FALSE, error))
-               return FALSE;
-
        /* Skip if already has reviews */
        if (gs_app_get_reviews (app)->len > 0)
                return TRUE;
@@ -908,9 +879,6 @@ set_review_usefulness (GsPlugin *plugin,
 {
        g_autofree gchar *path = NULL;
 
-       if (!get_ubuntuone_credentials (plugin, TRUE, error))
-               return FALSE;
-
        /* Create message for reviews.ubuntu.com */
        path = g_strdup_printf ("/api/1.0/reviews/%s/recommendations/?useful=%s", review_id, is_useful ? 
"True" : "False");
        return send_review_request (plugin, SOUP_METHOD_POST, path, NULL, TRUE, NULL, error);
@@ -925,9 +893,6 @@ report_review (GsPlugin *plugin,
 {
        g_autofree gchar *path = NULL;
 
-       if (!get_ubuntuone_credentials (plugin, TRUE, error))
-               return FALSE;
-
        /* Create message for reviews.ubuntu.com */
        // FIXME: escape reason / text properly
        path = g_strdup_printf ("/api/1.0/reviews/%s/recommendations/?reason=%s&text=%s", review_id, reason, 
text);
@@ -941,9 +906,6 @@ remove_review (GsPlugin *plugin,
 {
        g_autofree gchar *path = NULL;
 
-       if (!get_ubuntuone_credentials (plugin, TRUE, error))
-               return FALSE;
-
        /* Create message for reviews.ubuntu.com */
        path = g_strdup_printf ("/api/1.0/reviews/delete/%s/", review_id);
        return send_review_request (plugin, SOUP_METHOD_POST, path, NULL, TRUE, NULL, error);
@@ -964,9 +926,6 @@ gs_plugin_review_submit (GsPlugin *plugin,
                        return FALSE;
        }
 
-       if (!get_ubuntuone_credentials (plugin, TRUE, error))
-               return FALSE;
-
        return set_package_review (plugin,
                                   review,
                                   gs_app_get_source_default (app),
diff --git a/src/plugins/gs-plugin-ubuntuone.c b/src/plugins/gs-plugin-ubuntuone.c
new file mode 100644
index 0000000..5eeca99
--- /dev/null
+++ b/src/plugins/gs-plugin-ubuntuone.c
@@ -0,0 +1,266 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Canonical Ltd
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gs-utils.h>
+#include <gs-plugin.h>
+
+#include <string.h>
+#include <json-glib/json-glib.h>
+
+// Documented in http://canonical-identity-provider.readthedocs.io
+#define UBUNTU_LOGIN_HOST "https://login.ubuntu.com";
+
+struct GsPluginPrivate {
+       GsAuth *auth;
+};
+
+const gchar *
+gs_plugin_get_name (void)
+{
+       return "ubuntuone";
+}
+
+void
+gs_plugin_initialize (GsPlugin *plugin)
+{
+       /* create private area */
+       plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
+
+       /* check that we are running on Ubuntu */
+       if (!gs_plugin_check_distro_id (plugin, "ubuntu")) {
+               gs_plugin_set_enabled (plugin, FALSE);
+               g_debug ("disabling '%s' as we're not Ubuntu", plugin->name);
+               return;
+       }
+
+       plugin->priv->auth = gs_auth_new (plugin->name);
+       gs_auth_set_provider_name (plugin->priv->auth, "Ubuntu One");
+       gs_auth_set_provider_schema (plugin->priv->auth, "com.ubuntu.UbuntuOne.GnomeSoftware");
+        //gs_auth_set_provider_logo (plugin->priv->auth, "...");
+       gs_plugin_add_auth (plugin, plugin->priv->auth);
+}
+
+gboolean
+gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+{
+       /* load from disk */
+       gs_auth_add_metadata (plugin->priv->auth, "consumer-key", NULL);
+       gs_auth_add_metadata (plugin->priv->auth, "consumer-secret", NULL);
+       gs_auth_add_metadata (plugin->priv->auth, "token-key", NULL);
+       gs_auth_add_metadata (plugin->priv->auth, "token-secret", NULL);
+       if (!gs_auth_store_load (plugin->priv->auth,
+                                GS_AUTH_STORE_FLAG_USERNAME |
+                                GS_AUTH_STORE_FLAG_METADATA,
+                                cancellable, error))
+               return FALSE;
+
+       /* success */
+       return TRUE;
+}
+
+void
+gs_plugin_destroy (GsPlugin *plugin)
+{
+       g_clear_object (&plugin->priv->auth);
+}
+
+gboolean
+gs_plugin_auth_login (GsPlugin *plugin, GsAuth *auth,
+                     GCancellable *cancellable, GError **error)
+{
+       g_autoptr(JsonBuilder) builder = NULL;
+       g_autoptr(JsonNode) json_root = NULL;
+       g_autoptr(JsonGenerator) json_generator = NULL;
+       g_autofree gchar *data = NULL;
+       g_autofree gchar *uri = NULL;
+       g_autoptr(SoupMessage) msg = NULL;
+       guint status_code;
+       g_autoptr(JsonParser) parser = NULL;
+       JsonNode *response_root;
+       const gchar *tmp;
+
+       if (auth != plugin->priv->auth)
+               return TRUE;
+
+       builder = json_builder_new ();
+       json_builder_begin_object (builder);
+       json_builder_set_member_name (builder, "token_name");
+       json_builder_add_string_value (builder, "GNOME Software");
+       json_builder_set_member_name (builder, "email");
+       json_builder_add_string_value (builder, gs_auth_get_username (auth));
+       json_builder_set_member_name (builder, "password");
+       json_builder_add_string_value (builder, gs_auth_get_password (auth));
+       if (gs_auth_get_pin (auth)) {
+               json_builder_set_member_name (builder, "otp");
+               json_builder_add_string_value (builder, gs_auth_get_pin (auth));
+       }
+       json_builder_end_object (builder);
+
+       json_root = json_builder_get_root (builder);
+       json_generator = json_generator_new ();
+       json_generator_set_pretty (json_generator, TRUE);
+       json_generator_set_root (json_generator, json_root);
+       data = json_generator_to_data (json_generator, NULL);
+       if (data == NULL) {
+               g_set_error_literal (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_FAILED,
+                                    "Failed to generate JSON request");
+               return FALSE;
+       }
+
+       uri = g_strdup_printf ("%s/api/v2/tokens/oauth", UBUNTU_LOGIN_HOST);
+       msg = soup_message_new (SOUP_METHOD_POST, uri);
+       soup_message_set_request (msg, "application/json", SOUP_MEMORY_COPY, data, strlen (data));
+       status_code = soup_session_send_message (plugin->soup_session, msg);
+
+       parser = json_parser_new ();
+       if (!json_parser_load_from_data (parser, msg->response_body->data, -1, error)) {
+               return FALSE;
+       }
+       response_root = json_parser_get_root (parser);
+
+       if (status_code != SOUP_STATUS_OK) {
+               const gchar *message, *code;
+
+               message = json_object_get_string_member (json_node_get_object (response_root), "message");
+               code = json_object_get_string_member (json_node_get_object (response_root), "code");
+
+               if (g_strcmp0 (code, "INVALID_CREDENTIALS") == 0 ||
+                   g_strcmp0 (code, "EMAIL_INVALIDATED") == 0 ||
+                   g_strcmp0 (code, "TWOFACTOR_FAILURE") == 0) {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_AUTH_INVALID,
+                                            message);
+               /*} else if (g_strcmp0 (code, "ACCOUNT_SUSPENDED") == 0) {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_ACCOUNT_SUSPENDED,
+                                            message);
+               } else if (g_strcmp0 (code, "ACCOUNT_DEACTIVATED") == 0) {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_ACCOUNT_DEACTIVATED,
+                                            message);*/
+               } else if (g_strcmp0 (code, "TWOFACTOR_REQUIRED") == 0) {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_PIN_REQUIRED,
+                                            message);
+               } else {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_AUTH_INVALID,
+                                            message);
+               }
+               return FALSE;
+       }
+
+       /* consumer-key */
+       tmp = json_object_get_string_member (json_node_get_object (response_root), "consumer_key");
+       if (tmp == NULL) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "Response from %s missing required field consumer_key",
+                            UBUNTU_LOGIN_HOST);
+               return FALSE;
+       }
+       gs_auth_add_metadata (auth, "consumer-key", tmp);
+
+       /* consumer-secret */
+       tmp = json_object_get_string_member (json_node_get_object (response_root), "consumer_secret");
+       if (tmp == NULL) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "Response from %s missing required field consumer_secret",
+                            UBUNTU_LOGIN_HOST);
+               return FALSE;
+       }
+       gs_auth_add_metadata (auth, "consumer-secret", tmp);
+
+       /* token-key */
+       tmp = json_object_get_string_member (json_node_get_object (response_root), "token_key");
+       if (tmp == NULL) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "Response from %s missing required field token_key",
+                            UBUNTU_LOGIN_HOST);
+               return FALSE;
+       }
+       gs_auth_add_metadata (auth, "token-key", tmp);
+
+       /* token-secret */
+       tmp = json_object_get_string_member (json_node_get_object (response_root), "token_secret");
+       if (tmp == NULL) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "Response from %s missing required field token_secret",
+                            UBUNTU_LOGIN_HOST);
+               return FALSE;
+       }
+       gs_auth_add_metadata (auth, "token-secret", tmp);
+
+       /* store */
+       if (!gs_auth_store_save (auth,
+                                GS_AUTH_STORE_FLAG_USERNAME |
+                                GS_AUTH_STORE_FLAG_METADATA,
+                                cancellable, error))
+               return FALSE;
+
+       gs_auth_add_flags (plugin->priv->auth, GS_AUTH_FLAG_VALID);
+
+       return TRUE;
+}
+
+gboolean
+gs_plugin_auth_lost_password (GsPlugin *plugin, GsAuth *auth,
+                             GCancellable *cancellable, GError **error)
+{
+       if (auth != plugin->priv->auth)
+               return TRUE;
+
+       /* return with data */
+       g_set_error (error,
+                    GS_PLUGIN_ERROR,
+                    GS_PLUGIN_ERROR_AUTH_INVALID,
+                    "do online using @%s/+forgot_password", UBUNTU_LOGIN_HOST);
+       return FALSE;
+}
+
+gboolean
+gs_plugin_auth_register (GsPlugin *plugin, GsAuth *auth,
+                        GCancellable *cancellable, GError **error)
+{
+       if (auth != plugin->priv->auth)
+               return TRUE;
+
+       /* return with data */
+       g_set_error (error,
+                    GS_PLUGIN_ERROR,
+                    GS_PLUGIN_ERROR_AUTH_INVALID,
+                    "do online using @%s/+login", UBUNTU_LOGIN_HOST);
+       return FALSE;
+}
diff --git a/src/plugins/gs-snapd.c b/src/plugins/gs-snapd.c
index 261af42..4bc288e 100644
--- a/src/plugins/gs-snapd.c
+++ b/src/plugins/gs-snapd.c
@@ -25,7 +25,6 @@
 #include <libsoup/soup.h>
 #include <gio/gunixsocketaddress.h>
 #include "gs-snapd.h"
-#include "gs-ubuntuone.h"
 
 // snapd API documentation is at https://github.com/snapcore/snapd/blob/master/docs/rest.md
 
@@ -93,12 +92,8 @@ static gboolean
 send_request (const gchar  *method,
              const gchar  *path,
              const gchar  *content,
-             gboolean      authenticate,
-             const gchar  *macaroon_,
-             gchar       **discharges_,
-             gboolean      retry_after_login,
-             gchar       **out_macaroon,
-             gchar      ***out_discharges,
+             const gchar  *macaroon,
+             gchar       **discharges,
              guint        *status_code,
              gchar       **reason_phrase,
              gchar       **response_type,
@@ -113,17 +108,8 @@ send_request (const gchar  *method,
        g_autoptr (GByteArray) buffer = NULL;
        gsize data_length = 0, body_offset = 0;
        g_autoptr (SoupMessageHeaders) headers = NULL;
-       g_autofree gchar *macaroon = NULL;
-       g_auto(GStrv) discharges = NULL;
        gsize chunk_length = 0, n_required, chunk_offset;
        guint code;
-       gboolean ret;
-
-       macaroon = g_strdup (macaroon_);
-       discharges = g_strdupv (discharges_);
-       if (macaroon == NULL && authenticate) {
-               gs_ubuntuone_get_macaroon (TRUE, FALSE, &macaroon, &discharges, NULL);
-       }
 
        // NOTE: Would love to use libsoup but it doesn't support unix sockets
        // https://bugzilla.gnome.org/show_bug.cgi?id=727563
@@ -200,44 +186,6 @@ send_request (const gchar  *method,
        if (status_code != NULL)
                *status_code = code;
 
-       if ((code == 401 || code == 403) && retry_after_login) {
-               g_socket_close (socket, NULL);
-
-               gs_ubuntuone_clear_macaroon ();
-
-               g_clear_pointer (&macaroon, g_free);
-               g_clear_pointer (&discharges, g_strfreev);
-               gs_ubuntuone_get_macaroon (FALSE, TRUE, &macaroon, &discharges, NULL);
-
-               if (macaroon == NULL) {
-                       g_set_error_literal (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED,
-                                            "failed to authenticate");
-                       return FALSE;
-               }
-
-               ret = send_request (method,
-                                   path,
-                                   content,
-                                   TRUE,
-                                   macaroon, discharges,
-                                   FALSE,
-                                   NULL, NULL,
-                                   status_code,
-                                   reason_phrase,
-                                   response_type,
-                                   response,
-                                   response_length,
-                                   cancellable,
-                                   error);
-
-               if (ret && out_macaroon != NULL) {
-                       *out_macaroon = g_steal_pointer (&macaroon);
-                       *out_discharges = g_steal_pointer (&discharges);
-               }
-
-               return ret;
-       }
-
        /* read content */
        switch (soup_message_headers_get_encoding (headers)) {
        case SOUP_ENCODING_EOF:
@@ -323,10 +271,6 @@ send_request (const gchar  *method,
        }
 
 
-       if (out_macaroon != NULL) {
-               *out_macaroon = g_steal_pointer (&macaroon);
-               *out_discharges = g_steal_pointer (&discharges);
-       }
        if (response_type)
                *response_type = g_strdup (soup_message_headers_get_content_type (headers, NULL));
        if (response != NULL) {
@@ -392,8 +336,7 @@ gs_snapd_get_system_info (GCancellable *cancellable, GError **error)
        JsonObject *root, *result;
 
        if (!send_request ("GET", "/v2/system-info", NULL,
-                          TRUE, NULL, NULL,
-                          TRUE, NULL, NULL,
+                          NULL, NULL,
                           &status_code, &reason_phrase,
                           &response_type, &response, NULL,
                           cancellable, error))
@@ -425,7 +368,8 @@ gs_snapd_get_system_info (GCancellable *cancellable, GError **error)
 }
 
 JsonObject *
-gs_snapd_list_one (const gchar *name,
+gs_snapd_list_one (const gchar *macaroon, gchar **discharges,
+                  const gchar *name,
                   GCancellable *cancellable, GError **error)
 {
        g_autofree gchar *path = NULL;
@@ -438,8 +382,7 @@ gs_snapd_list_one (const gchar *name,
 
        path = g_strdup_printf ("/v2/snaps/%s", name);
        if (!send_request ("GET", path, NULL,
-                          TRUE, NULL, NULL,
-                          TRUE, NULL, NULL,
+                          macaroon, discharges,
                           &status_code, &reason_phrase,
                           &response_type, &response, NULL,
                           cancellable, error))
@@ -471,7 +414,8 @@ gs_snapd_list_one (const gchar *name,
 }
 
 JsonArray *
-gs_snapd_list (GCancellable *cancellable, GError **error)
+gs_snapd_list (const gchar *macaroon, gchar **discharges,
+              GCancellable *cancellable, GError **error)
 {
        guint status_code;
        g_autofree gchar *reason_phrase = NULL;
@@ -482,8 +426,7 @@ gs_snapd_list (GCancellable *cancellable, GError **error)
        JsonArray *result;
 
        if (!send_request ("GET", "/v2/snaps", NULL,
-                          TRUE, NULL, NULL,
-                          TRUE, NULL, NULL,
+                          macaroon, discharges,
                           &status_code, &reason_phrase,
                           &response_type, &response, NULL,
                           cancellable, error))
@@ -515,7 +458,8 @@ gs_snapd_list (GCancellable *cancellable, GError **error)
 }
 
 JsonArray *
-gs_snapd_find (const gchar *section, gboolean match_name, const gchar *query,
+gs_snapd_find (const gchar *macaroon, gchar **discharges,
+              const gchar *section, gboolean match_name, const gchar *query,
               GCancellable *cancellable, GError **error)
 {
        g_autoptr(GString) path = NULL;
@@ -544,8 +488,7 @@ gs_snapd_find (const gchar *section, gboolean match_name, const gchar *query,
                g_string_append (path, escaped);
        }
        if (!send_request ("GET", path->str, NULL,
-                          TRUE, NULL, NULL,
-                          TRUE, NULL, NULL,
+                          macaroon, discharges,
                           &status_code, &reason_phrase,
                           &response_type, &response, NULL,
                           cancellable, error))
@@ -577,7 +520,7 @@ gs_snapd_find (const gchar *section, gboolean match_name, const gchar *query,
 }
 
 JsonObject *
-gs_snapd_get_interfaces (GCancellable *cancellable, GError **error)
+gs_snapd_get_interfaces (const gchar *macaroon, gchar **discharges, GCancellable *cancellable, GError 
**error)
 {
        guint status_code;
        g_autofree gchar *reason_phrase = NULL;
@@ -588,8 +531,7 @@ gs_snapd_get_interfaces (GCancellable *cancellable, GError **error)
        JsonObject *result;
 
        if (!send_request ("GET", "/v2/interfaces", NULL,
-                          TRUE, NULL, NULL,
-                          TRUE, NULL, NULL,
+                          macaroon, discharges,
                           &status_code, &reason_phrase,
                           &response_type, &response, NULL,
                           cancellable, error))
@@ -635,8 +577,7 @@ get_changes (const gchar *macaroon, gchar **discharges,
 
        path = g_strdup_printf ("/v2/changes/%s", change_id);
        if (!send_request ("GET", path, NULL,
-                          TRUE, macaroon, discharges,
-                          TRUE, NULL, NULL,
+                          macaroon, discharges,
                           &status_code, &reason_phrase,
                           &response_type, &response, NULL,
                           cancellable, error))
@@ -668,7 +609,9 @@ get_changes (const gchar *macaroon, gchar **discharges,
 }
 
 static gboolean
-send_package_action (const gchar *name,
+send_package_action (const gchar *macaroon,
+                    gchar **discharges,
+                    const gchar *name,
                     const gchar *action,
                     GsSnapdProgressCallback callback,
                     gpointer user_data,
@@ -677,8 +620,6 @@ send_package_action (const gchar *name,
 {
        g_autofree gchar *content = NULL, *path = NULL;
        guint status_code;
-       g_autofree gchar *macaroon = NULL;
-       g_auto(GStrv) discharges = NULL;
        g_autofree gchar *reason_phrase = NULL;
        g_autofree gchar *response_type = NULL;
        g_autofree gchar *response = NULL;
@@ -690,13 +631,20 @@ send_package_action (const gchar *name,
        content = g_strdup_printf ("{\"action\": \"%s\"}", action);
        path = g_strdup_printf ("/v2/snaps/%s", name);
        if (!send_request ("POST", path, content,
-                          TRUE, NULL, NULL,
-                          TRUE, &macaroon, &discharges,
+                          macaroon, discharges,
                           &status_code, &reason_phrase,
                           &response_type, &response, NULL,
                           cancellable, error))
                return FALSE;
 
+       if (status_code == SOUP_STATUS_UNAUTHORIZED) {
+               g_set_error_literal (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_AUTH_REQUIRED,
+                                    "Requires authentication with @snapd");
+               return FALSE;
+       }
+
        if (status_code != SOUP_STATUS_ACCEPTED) {
                g_set_error (error,
                             GS_PLUGIN_ERROR,
@@ -747,24 +695,27 @@ send_package_action (const gchar *name,
 }
 
 gboolean
-gs_snapd_install (const gchar *name,
+gs_snapd_install (const gchar *macaroon, gchar **discharges,
+                 const gchar *name,
                  GsSnapdProgressCallback callback, gpointer user_data,
                  GCancellable *cancellable,
                  GError **error)
 {
-       return send_package_action (name, "install", callback, user_data, cancellable, error);
+       return send_package_action (macaroon, discharges, name, "install", callback, user_data, cancellable, 
error);
 }
 
 gboolean
-gs_snapd_remove (const gchar *name,
+gs_snapd_remove (const gchar *macaroon, gchar **discharges,
+                const gchar *name,
                 GsSnapdProgressCallback callback, gpointer user_data,
                 GCancellable *cancellable, GError **error)
 {
-       return send_package_action (name, "remove", callback, user_data, cancellable, error);
+       return send_package_action (macaroon, discharges, name, "remove", callback, user_data, cancellable, 
error);
 }
 
 gchar *
-gs_snapd_get_resource (const gchar *path,
+gs_snapd_get_resource (const gchar *macaroon, gchar **discharges,
+                      const gchar *path,
                       gsize *data_length,
                       GCancellable *cancellable, GError **error)
 {
@@ -774,8 +725,7 @@ gs_snapd_get_resource (const gchar *path,
        g_autofree gchar *data = NULL;
 
        if (!send_request ("GET", path, NULL,
-                          TRUE, NULL, NULL,
-                          TRUE, NULL, NULL,
+                          macaroon, discharges,
                           &status_code, &reason_phrase,
                           NULL, &data, data_length,
                           cancellable, error))
diff --git a/src/plugins/gs-snapd.h b/src/plugins/gs-snapd.h
index c75cdf2..c9a0ae5 100644
--- a/src/plugins/gs-snapd.h
+++ b/src/plugins/gs-snapd.h
@@ -27,38 +27,52 @@
 
 typedef void (*GsSnapdProgressCallback) (JsonObject *object, gpointer user_data);
 
-JsonObject *gs_snapd_get_system_info   (GCancellable   *cancellable,
-                                       GError          **error);
+JsonObject *gs_snapd_get_system_info   (GCancellable   *cancellable,
+                                        GError         **error);
 
-JsonObject *gs_snapd_list_one          (const gchar    *name,
+JsonObject *gs_snapd_list_one          (const gchar    *macaroon,
+                                        gchar          **discharges,
+                                        const gchar    *name,
                                         GCancellable   *cancellable,
                                         GError         **error);
 
-JsonArray *gs_snapd_list               (GCancellable   *cancellable,
+JsonArray *gs_snapd_list               (const gchar    *macaroon,
+                                        gchar          **discharges,
+                                        GCancellable   *cancellable,
                                         GError         **error);
 
-JsonArray *gs_snapd_find               (const gchar    *section,
+JsonArray *gs_snapd_find               (const gchar    *macaroon,
+                                        gchar          **discharges,
+                                        const gchar    *section,
                                         gboolean        match_name,
                                         const gchar    *query,
                                         GCancellable   *cancellable,
                                         GError         **error);
 
-JsonObject *gs_snapd_get_interfaces    (GCancellable   *cancellable,
+JsonObject *gs_snapd_get_interfaces    (const gchar    *macaroon,
+                                        gchar          **discharges,
+                                        GCancellable   *cancellable,
                                         GError         **error);
 
-gboolean gs_snapd_install              (const gchar    *name,
+gboolean gs_snapd_install              (const gchar    *macaroon,
+                                        gchar          **discharges,
+                                        const gchar    *name,
                                         GsSnapdProgressCallback callback,
                                         gpointer        user_data,
                                         GCancellable   *cancellable,
                                         GError         **error);
 
-gboolean gs_snapd_remove               (const gchar    *name,
+gboolean gs_snapd_remove               (const gchar    *macaroon,
+                                        gchar          **discharges,
+                                        const gchar    *name,
                                         GsSnapdProgressCallback callback,
                                         gpointer        user_data,
                                         GCancellable   *cancellable,
                                         GError         **error);
 
-gchar *gs_snapd_get_resource           (const gchar    *path,
+gchar *gs_snapd_get_resource           (const gchar    *macaroon,
+                                        gchar          **discharges,
+                                        const gchar    *path,
                                         gsize          *data_length,
                                         GCancellable   *cancellable,
                                         GError         **error);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]