[gnome-software] Do not set invalid application states on error



commit b71d325a4986ed3bf7f707a07c77ce8d618d0223
Author: Richard Hughes <richard hughsie com>
Date:   Sun Apr 17 11:32:40 2016 +0100

    Do not set invalid application states on error
    
    Now plugins can fail without stopping the loader we have to make them
    responsible for setting the correct non-transient states when completed.
    
    Provide a helper called gs_app_set_state_recover() which can be used to un-set
    any transient states in the error handler.

 src/gs-app.c                                |   27 ++++++++++++
 src/gs-app.h                                |    1 +
 src/gs-plugin-loader.c                      |   58 +++++++++-----------------
 src/gs-self-test.c                          |   41 +++++++++++++++++++
 src/plugins/gs-plugin-dummy.c               |   52 ++++++++++++++++++++++++
 src/plugins/gs-plugin-fedora-tagger-usage.c |    4 ++
 src/plugins/gs-plugin-fwupd.c               |    4 +-
 src/plugins/gs-plugin-packagekit.c          |   37 ++++++++++++++---
 src/plugins/gs-plugin-shell-extensions.c    |   19 +++++++-
 src/plugins/gs-plugin-xdg-app.c             |   41 ++++++++++++++-----
 10 files changed, 225 insertions(+), 59 deletions(-)
---
diff --git a/src/gs-app.c b/src/gs-app.c
index b1ee04c..84decc3 100644
--- a/src/gs-app.c
+++ b/src/gs-app.c
@@ -89,6 +89,7 @@ struct _GsApp
        guint64                  size;
        AsAppKind                kind;
        AsAppState               state;
+       AsAppState               state_recover;
        guint                    progress;
        GHashTable              *metadata;
        GdkPixbuf               *pixbuf;
@@ -436,6 +437,19 @@ gs_app_get_progress (GsApp *app)
 }
 
 /**
+ * gs_app_set_state_recover:
+ *
+ * Sets the application state to the last status value that was not
+ * transient.
+ */
+void
+gs_app_set_state_recover (GsApp *app)
+{
+       if (app->state_recover != AS_APP_STATE_UNKNOWN)
+               gs_app_set_state (app, app->state_recover);
+}
+
+/**
  * gs_app_set_state_internal:
  */
 static gboolean
@@ -539,6 +553,19 @@ gs_app_set_state_internal (GsApp *app, AsAppState state)
            state == AS_APP_STATE_AVAILABLE)
                app->install_date = 0;
 
+       /* save this to simplify error handling in the plugins */
+       switch (state) {
+       case AS_APP_STATE_INSTALLING:
+       case AS_APP_STATE_REMOVING:
+               /* transient, so ignore */
+               break;
+       default:
+               g_debug ("non-transient state now %s",
+                        as_app_state_to_string (state));
+               app->state_recover = state;
+               break;
+       }
+
        return TRUE;
 }
 
diff --git a/src/gs-app.h b/src/gs-app.h
index ab170fe..8b1ff4d 100644
--- a/src/gs-app.h
+++ b/src/gs-app.h
@@ -100,6 +100,7 @@ void                 gs_app_set_kind                (GsApp          *app,
 AsAppState      gs_app_get_state               (GsApp          *app);
 void            gs_app_set_state               (GsApp          *app,
                                                 AsAppState      state);
+void            gs_app_set_state_recover       (GsApp          *app);
 guint           gs_app_get_progress            (GsApp          *app);
 void            gs_app_set_progress            (GsApp          *app,
                                                 guint           percentage);
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index 4784ee6..68fa9e7 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -74,8 +74,6 @@ typedef struct {
        GsCategory                      *category;
        GsApp                           *app;
        GsReview                        *review;
-       AsAppState                       state_success;
-       AsAppState                       state_failure;
 } GsPluginLoaderAsyncState;
 
 static void
@@ -2419,16 +2417,12 @@ gs_plugin_loader_app_action_thread_cb (GTask *task,
                                           cancellable,
                                           &error);
        if (ret) {
-               if (state->state_success != AS_APP_STATE_UNKNOWN) {
-                       gs_app_set_state (state->app, state->state_success);
-                       addons = gs_app_get_addons (state->app);
-                       for (i = 0; i < addons->len; i++) {
-                               GsApp *addon = g_ptr_array_index (addons, i);
-                               if (gs_app_get_to_be_installed (addon)) {
-                                       gs_app_set_state (addon, state->state_success);
-                                       gs_app_set_to_be_installed (addon, FALSE);
-                               }
-                       }
+               /* unstage addons */
+               addons = gs_app_get_addons (state->app);
+               for (i = 0; i < addons->len; i++) {
+                       GsApp *addon = g_ptr_array_index (addons, i);
+                       if (gs_app_get_to_be_installed (addon))
+                               gs_app_set_to_be_installed (addon, FALSE);
                }
 
                /* refine again to make sure we pick up new source id */
@@ -2445,20 +2439,22 @@ gs_plugin_loader_app_action_thread_cb (GTask *task,
                        g_task_return_error (task, error);
                }
        } else {
-               if (state->state_failure != AS_APP_STATE_UNKNOWN) {
-                       gs_app_set_state (state->app, state->state_failure);
-                       addons = gs_app_get_addons (state->app);
-                       for (i = 0; i < addons->len; i++) {
-                               GsApp *addon = g_ptr_array_index (addons, i);
-                               if (gs_app_get_to_be_installed (addon)) {
-                                       gs_app_set_state (addon, state->state_failure);
-                                       gs_app_set_to_be_installed (addon, FALSE);
-                               }
-                       }
-               }
                g_task_return_error (task, error);
        }
 
+       /* check the app is not still in an action state */
+       switch (gs_app_get_state (state->app)) {
+       case AS_APP_STATE_INSTALLING:
+       case AS_APP_STATE_REMOVING:
+               g_warning ("application %s left in %s state",
+                          gs_app_get_id (state->app),
+                          as_app_state_to_string (gs_app_get_state (state->app)));
+               gs_app_set_state (state->app, AS_APP_STATE_UNKNOWN);
+               break;
+       default:
+               break;
+       }
+
        /* remove from list */
        g_mutex_lock (&priv->pending_apps_mutex);
        g_ptr_array_remove (priv->pending_apps, state->app);
@@ -2745,38 +2741,24 @@ gs_plugin_loader_app_action_async (GsPluginLoader *plugin_loader,
        switch (action) {
        case GS_PLUGIN_LOADER_ACTION_INSTALL:
                state->function_name = "gs_plugin_app_install";
-               state->state_success = AS_APP_STATE_INSTALLED;
-               state->state_failure = AS_APP_STATE_AVAILABLE;
                break;
        case GS_PLUGIN_LOADER_ACTION_REMOVE:
                state->function_name = "gs_plugin_app_remove";
-               state->state_success = AS_APP_STATE_AVAILABLE;
-               state->state_failure = AS_APP_STATE_INSTALLED;
                break;
        case GS_PLUGIN_LOADER_ACTION_SET_RATING:
                state->function_name = "gs_plugin_app_set_rating";
-               state->state_success = AS_APP_STATE_UNKNOWN;
-               state->state_failure = AS_APP_STATE_UNKNOWN;
                break;
        case GS_PLUGIN_LOADER_ACTION_UPGRADE_DOWNLOAD:
                state->function_name = "gs_plugin_app_upgrade_download";
-               state->state_success = AS_APP_STATE_UPDATABLE;
-               state->state_failure = AS_APP_STATE_AVAILABLE;
                break;
        case GS_PLUGIN_LOADER_ACTION_UPGRADE_TRIGGER:
                state->function_name = "gs_plugin_app_upgrade_trigger";
-               state->state_success = AS_APP_STATE_UNKNOWN;
-               state->state_failure = AS_APP_STATE_UNKNOWN;
                break;
        case GS_PLUGIN_LOADER_ACTION_LAUNCH:
                state->function_name = "gs_plugin_launch";
-               state->state_success = AS_APP_STATE_UNKNOWN;
-               state->state_failure = AS_APP_STATE_UNKNOWN;
                break;
        case GS_PLUGIN_LOADER_ACTION_UPDATE_CANCEL:
                state->function_name = "gs_plugin_update_cancel";
-               state->state_success = AS_APP_STATE_UNKNOWN;
-               state->state_failure = AS_APP_STATE_UNKNOWN;
                break;
        default:
                g_assert_not_reached ();
@@ -3549,7 +3531,7 @@ gs_plugin_loader_set_network_status (GsPluginLoader *plugin_loader,
        if (priv->online == online)
                return;
 
-       g_debug ("*** Network status change: %s", online ? "online" : "offline");
+       g_debug ("network status change: %s", online ? "online" : "offline");
 
        priv->online = online;
 
diff --git a/src/gs-self-test.c b/src/gs-self-test.c
index 2f5655c..cfbf395 100644
--- a/src/gs-self-test.c
+++ b/src/gs-self-test.c
@@ -144,6 +144,14 @@ gs_app_func (void)
        g_assert_cmpstr (gs_app_get_name (app), ==, "dave");
        gs_app_set_name (app, GS_APP_QUALITY_HIGHEST, "hugh");
        g_assert_cmpstr (gs_app_get_name (app), ==, "hugh");
+
+       /* check non-transient state saving */
+       gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
+       gs_app_set_state (app, AS_APP_STATE_REMOVING);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_REMOVING);
+       gs_app_set_state_recover (app); // simulate an error
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
 }
 
 static guint _status_changed_cnt = 0;
@@ -157,6 +165,35 @@ gs_plugin_loader_status_changed_cb (GsPluginLoader *plugin_loader,
        _status_changed_cnt++;
 }
 
+static void
+gs_plugin_loader_install_func (GsPluginLoader *plugin_loader)
+{
+       gboolean ret;
+       g_autoptr(GsApp) app = NULL;
+       g_autoptr(GError) error = NULL;
+
+       /* install */
+       app = gs_app_new ("chiron.desktop");
+       gs_app_set_management_plugin (app, "dummy");
+       gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+       ret = gs_plugin_loader_app_action (plugin_loader, app,
+                                          GS_PLUGIN_LOADER_ACTION_INSTALL,
+                                          NULL,
+                                          &error);
+       g_assert_no_error (error);
+       g_assert (ret);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
+
+       /* remove -- we're really testing for return code UNKNOWN,
+        * but dummy::refine() sets it */
+       ret = gs_plugin_loader_app_action (plugin_loader, app,
+                                          GS_PLUGIN_LOADER_ACTION_REMOVE,
+                                          NULL,
+                                          &error);
+       g_assert_no_error (error);
+       g_assert (ret);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
+}
 
 static void
 gs_plugin_loader_refine_func (GsPluginLoader *plugin_loader)
@@ -456,6 +493,7 @@ main (int argc, char **argv)
 
        /* we can only load this once per process */
        plugin_loader = gs_plugin_loader_new ();
+       gs_plugin_loader_set_network_status (plugin_loader, TRUE);
        g_signal_connect (plugin_loader, "status-changed",
                          G_CALLBACK (gs_plugin_loader_status_changed_cb), NULL);
        gs_plugin_loader_set_location (plugin_loader, "./plugins/.libs");
@@ -474,6 +512,9 @@ main (int argc, char **argv)
        g_test_add_data_func ("/gnome-software/plugin-loader{search}",
                              plugin_loader,
                              (GTestDataFunc) gs_plugin_loader_search_func);
+       g_test_add_data_func ("/gnome-software/plugin-loader{install}",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugin_loader_install_func);
        g_test_add_data_func ("/gnome-software/plugin-loader{installed}",
                              plugin_loader,
                              (GTestDataFunc) gs_plugin_loader_installed_func);
diff --git a/src/plugins/gs-plugin-dummy.c b/src/plugins/gs-plugin-dummy.c
index 946cb14..c5862b5 100644
--- a/src/plugins/gs-plugin-dummy.c
+++ b/src/plugins/gs-plugin-dummy.c
@@ -56,6 +56,7 @@ void
 gs_plugin_adopt_app (GsPlugin *plugin, GsApp *app)
 {
        if (g_strcmp0 (gs_app_get_id (app), "mate-spell.desktop") == 0 ||
+           g_strcmp0 (gs_app_get_id (app), "chiron.desktop") == 0 ||
            g_strcmp0 (gs_app_get_id (app), "zeus.desktop") == 0 ||
            g_strcmp0 (gs_app_get_id (app), "zeus-spell.addon") == 0)
                gs_app_set_management_plugin (app, plugin->name);
@@ -246,6 +247,56 @@ gs_plugin_add_installed (GsPlugin *plugin,
 }
 
 /**
+ * gs_plugin_app_remove:
+ */
+gboolean
+gs_plugin_app_remove (GsPlugin *plugin,
+                     GsApp *app,
+                     GCancellable *cancellable,
+                     GError **error)
+{
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
+               return TRUE;
+
+       /* remove app */
+       if (g_strcmp0 (gs_app_get_id (app), "chiron.desktop") == 0) {
+               gs_app_set_state (app, AS_APP_STATE_REMOVING);
+               if (!gs_plugin_dummy_delay (plugin, app, 500, cancellable, error)) {
+                       gs_app_set_state_recover (app);
+                       return FALSE;
+               }
+               gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
+       }
+       return TRUE;
+}
+
+/**
+ * gs_plugin_app_install:
+ */
+gboolean
+gs_plugin_app_install (GsPlugin *plugin,
+                      GsApp *app,
+                      GCancellable *cancellable,
+                      GError **error)
+{
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
+               return TRUE;
+
+       /* install app */
+       if (g_strcmp0 (gs_app_get_id (app), "chiron.desktop") == 0) {
+               gs_app_set_state (app, AS_APP_STATE_INSTALLING);
+               if (!gs_plugin_dummy_delay (plugin, app, 500, cancellable, error)) {
+                       gs_app_set_state_recover (app);
+                       return FALSE;
+               }
+               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+       }
+       return TRUE;
+}
+
+/**
  * gs_plugin_refine_app:
  */
 gboolean
@@ -421,6 +472,7 @@ gs_plugin_app_upgrade_download (GsPlugin *plugin, GsApp *app,
        gs_app_set_state (app, AS_APP_STATE_INSTALLING);
        if (!gs_plugin_dummy_delay (plugin, app, 5000, cancellable, error))
                return FALSE;
+       gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
        return TRUE;
 }
 
diff --git a/src/plugins/gs-plugin-fedora-tagger-usage.c b/src/plugins/gs-plugin-fedora-tagger-usage.c
index a71f8a5..e2665ab 100644
--- a/src/plugins/gs-plugin-fedora-tagger-usage.c
+++ b/src/plugins/gs-plugin-fedora-tagger-usage.c
@@ -164,6 +164,8 @@ gs_plugin_app_install (GsPlugin *plugin,
                       GCancellable *cancellable,
                       GError **error)
 {
+       if (gs_app_get_state (app) != AS_APP_STATE_INSTALLED)
+               return TRUE;
        return gs_plugin_app_set_usage_app (plugin, app, TRUE, error);
 }
 
@@ -176,5 +178,7 @@ gs_plugin_app_remove (GsPlugin *plugin,
                      GCancellable *cancellable,
                      GError **error)
 {
+       if (gs_app_get_state (app) != AS_APP_STATE_AVAILABLE)
+               return TRUE;
        return gs_plugin_app_set_usage_app (plugin, app, FALSE, error);
 }
diff --git a/src/plugins/gs-plugin-fwupd.c b/src/plugins/gs-plugin-fwupd.c
index 5e36f5f..e326903 100644
--- a/src/plugins/gs-plugin-fwupd.c
+++ b/src/plugins/gs-plugin-fwupd.c
@@ -660,8 +660,10 @@ gs_plugin_fwupd_install (GsPlugin *plugin,
        gs_app_set_state (app, AS_APP_STATE_INSTALLING);
        if (!fwupd_client_install (plugin->priv->client, device_id,
                                   filename, install_flags,
-                                  cancellable, error))
+                                  cancellable, error)) {
+               gs_app_set_state_recover (app);
                return FALSE;
+       }
        gs_app_set_state (app, AS_APP_STATE_INSTALLED);
        return TRUE;
 }
diff --git a/src/plugins/gs-plugin-packagekit.c b/src/plugins/gs-plugin-packagekit.c
index 9cc7640..cc83028 100644
--- a/src/plugins/gs-plugin-packagekit.c
+++ b/src/plugins/gs-plugin-packagekit.c
@@ -364,13 +364,15 @@ gs_plugin_app_install (GsPlugin *plugin,
                                                         gs_plugin_packagekit_progress_cb, &data,
                                                         error);
                if (results == NULL) {
-                       gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+                       gs_app_set_state_recover (app);
                        return FALSE;
                }
 
+               /* state is known */
+               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+
                /* no longer valid */
                gs_app_clear_source_ids (app);
-               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
                return TRUE;
        }
 
@@ -430,8 +432,14 @@ gs_plugin_app_install (GsPlugin *plugin,
                                                         cancellable,
                                                         gs_plugin_packagekit_progress_cb, &data,
                                                         error);
-               if (results == NULL)
+               if (results == NULL) {
+                       gs_app_set_state_recover (app);
                        return FALSE;
+               }
+
+               /* state is known */
+               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+
                break;
        case AS_APP_STATE_AVAILABLE_LOCAL:
                package_id = gs_app_get_metadata_item (app, "packagekit::local-filename");
@@ -449,8 +457,13 @@ gs_plugin_app_install (GsPlugin *plugin,
                                                      cancellable,
                                                      gs_plugin_packagekit_progress_cb, &data,
                                                      error);
-               if (results == NULL)
+               if (results == NULL) {
+                       gs_app_set_state_recover (app);
                        return FALSE;
+               }
+
+               /* state is known */
+               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
 
                /* get the new icon from the package */
                gs_app_set_metadata (app, "packagekit::local-filename", NULL);
@@ -610,8 +623,13 @@ gs_plugin_app_remove (GsPlugin *plugin,
                                                cancellable,
                                                gs_plugin_packagekit_progress_cb, &data,
                                                error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_app_set_state_recover (app);
                return FALSE;
+       }
+
+       /* state is not known: we don't know if we can re-install this app */
+       gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
 
        /* no longer valid */
        gs_app_clear_source_ids (app);
@@ -665,7 +683,14 @@ gs_plugin_app_upgrade_download (GsPlugin *plugin,
                                            cancellable,
                                            gs_plugin_packagekit_progress_cb, &data,
                                            error);
-       return results != NULL;
+       if (results == NULL) {
+               gs_app_set_state_recover (app);
+               return FALSE;
+       }
+
+       /* state is known */
+       gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
+       return TRUE;
 }
 
 /**
diff --git a/src/plugins/gs-plugin-shell-extensions.c b/src/plugins/gs-plugin-shell-extensions.c
index 7645bbe..8124d15 100644
--- a/src/plugins/gs-plugin-shell-extensions.c
+++ b/src/plugins/gs-plugin-shell-extensions.c
@@ -728,7 +728,8 @@ gs_plugin_app_remove (GsPlugin *plugin,
        if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
-       /* install */
+       /* remove */
+       gs_app_set_state (app, AS_APP_STATE_REMOVING);
        uuid = gs_app_get_metadata_item (app, "shell-extensions::uuid");
        retval = g_dbus_proxy_call_sync (plugin->priv->proxy,
                                         "UninstallExtension",
@@ -737,12 +738,15 @@ gs_plugin_app_remove (GsPlugin *plugin,
                                         -1,
                                         cancellable,
                                         error);
-       if (retval == NULL)
+       if (retval == NULL) {
+               gs_app_set_state_recover (app);
                return FALSE;
+       }
 
        /* not sure why this would fail -- perhaps installed in /usr? */
        g_variant_get (retval, "(b)", &ret);
        if (!ret) {
+               gs_app_set_state_recover (app);
                g_set_error (error,
                             GS_PLUGIN_ERROR,
                             GS_PLUGIN_ERROR_FAILED,
@@ -751,6 +755,9 @@ gs_plugin_app_remove (GsPlugin *plugin,
                return FALSE;
        }
 
+       /* state is not known: we don't know if we can re-install this app */
+       gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
+
        return TRUE;
 }
 
@@ -781,12 +788,15 @@ gs_plugin_app_install (GsPlugin *plugin,
                                         -1,
                                         cancellable,
                                         error);
-       if (retval == NULL)
+       if (retval == NULL) {
+               gs_app_set_state_recover (app);
                return FALSE;
+       }
        g_variant_get (retval, "(&s)", &retstr);
 
        /* user declined download */
        if (g_strcmp0 (retstr, "cancelled") == 0) {
+               gs_app_set_state_recover (app);
                g_set_error (error,
                             GS_PLUGIN_ERROR,
                             GS_PLUGIN_ERROR_CANCELLED,
@@ -795,6 +805,9 @@ gs_plugin_app_install (GsPlugin *plugin,
                return FALSE;
        }
        g_debug ("shell returned: %s", retstr);
+
+       /* state is known */
+       gs_app_set_state (app, AS_APP_STATE_INSTALLED);
        return TRUE;
 }
 
diff --git a/src/plugins/gs-plugin-xdg-app.c b/src/plugins/gs-plugin-xdg-app.c
index 5e6e1c0..bb9da8b 100644
--- a/src/plugins/gs-plugin-xdg-app.c
+++ b/src/plugins/gs-plugin-xdg-app.c
@@ -1220,13 +1220,20 @@ gs_plugin_app_remove (GsPlugin *plugin,
 
        /* remove */
        gs_app_set_state (app, AS_APP_STATE_REMOVING);
-       return xdg_app_installation_uninstall (plugin->priv->installation,
-                                              XDG_APP_REF_KIND_APP,
-                                              gs_app_get_xdgapp_name (app),
-                                              gs_app_get_xdgapp_arch (app),
-                                              gs_app_get_xdgapp_branch (app),
-                                              gs_plugin_xdg_app_progress_cb, &helper,
-                                              cancellable, error);
+       if (!xdg_app_installation_uninstall (plugin->priv->installation,
+                                            XDG_APP_REF_KIND_APP,
+                                            gs_app_get_xdgapp_name (app),
+                                            gs_app_get_xdgapp_arch (app),
+                                            gs_app_get_xdgapp_branch (app),
+                                            gs_plugin_xdg_app_progress_cb, &helper,
+                                            cancellable, error)) {
+               gs_app_set_state_recover (app);
+               return FALSE;
+       }
+
+       /* state is not known: we don't know if we can re-install this app */
+       gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
+       return TRUE;
 }
 
 /**
@@ -1291,7 +1298,7 @@ gs_plugin_app_install (GsPlugin *plugin,
                                                             gs_plugin_xdg_app_progress_cb, &helper,
                                                             cancellable, error);
                        if (xref == NULL) {
-                               gs_app_set_state (runtime, AS_APP_STATE_AVAILABLE);
+                               gs_app_set_state_recover (runtime);
                                return FALSE;
                        }
                        gs_app_set_state (runtime, AS_APP_STATE_INSTALLED);
@@ -1321,9 +1328,14 @@ gs_plugin_app_install (GsPlugin *plugin,
                                                     gs_plugin_xdg_app_progress_cb, &helper,
                                                     cancellable, error);
        }
+       if (xref == NULL) {
+               gs_app_set_state_recover (app);
+               return FALSE;
+       }
 
-       /* now the main application */
-       return xref != NULL;
+       /* state is known */
+       gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+       return TRUE;
 }
 
 /**
@@ -1356,7 +1368,14 @@ gs_plugin_update_app (GsPlugin *plugin,
                                            gs_app_get_xdgapp_branch (app),
                                            gs_plugin_xdg_app_progress_cb, &helper,
                                            cancellable, error);
-       return xref != NULL;
+       if (xref == NULL) {
+               gs_app_set_state_recover (app);
+               return FALSE;
+       }
+
+       /* state is known */
+       gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+       return TRUE;
 }
 
 /**


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