[gnome-software] Hide updates UI on managed systems



commit 0974ae1c80ed6de3aa10a6f3cb6b9b3ae5af3d66
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu May 21 18:01:15 2015 -0400

    Hide updates UI on managed systems
    
    It doesn't make sense to show the updates UI to a user
    who does not have the trigger-offline-updates privilege,
    so hide the Updates tab button in this case, and don't
    notify the user about available updates.
    
    If the user manages to open the updates tab anyway (e.g.
    by using the --mode=updates commandline option), tell him
    that updates are managed.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=749744

 configure.ac             |    1 +
 src/Makefile.am          |    2 ++
 src/gs-application.c     |   27 ++++++++++++++++++++++++++-
 src/gs-offline-updates.c |   27 +++++++++++++++++++++++++++
 src/gs-offline-updates.h |    3 +++
 src/gs-shell-updates.c   |   42 +++++++++++++++++++++++++++++++++++++++++-
 src/gs-shell-updates.ui  |   37 +++++++++++++++++++++++++++++++++++++
 src/gs-shell.c           |   28 ++++++++++++++++++++++++++++
 8 files changed, 165 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 9e9d612..acc11e7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,6 +66,7 @@ PKG_CHECK_MODULES(SQLITE, sqlite3)
 PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.42)
 PKG_CHECK_MODULES(GSETTINGS_DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.11.5)
 PKG_CHECK_MODULES(GNOME_DESKTOP, gnome-desktop-3.0)
+PKG_CHECK_MODULES(POLKIT, polkit-gobject-1)
 AC_PATH_PROG(APPSTREAM_UTIL, [appstream-util], [unfound])
 AC_ARG_ENABLE(man,
               [AS_HELP_STRING([--enable-man],
diff --git a/src/Makefile.am b/src/Makefile.am
index e4e91c2..840c539 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,6 +8,7 @@ AM_CPPFLAGS =                                           \
        $(SOUP_CFLAGS)                                  \
        $(PACKAGEKIT_CFLAGS)                            \
        $(GNOME_DESKTOP_CFLAGS)                         \
+       $(POLKIT_CFLAGS)                                \
        -DG_LOG_DOMAIN=\"Gs\"                           \
        -DI_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE  \
        -DGS_MODULESETDIR=\"$(datadir)/gnome-software/modulesets.d\" \
@@ -195,6 +196,7 @@ gnome_software_LDADD =                                      \
        $(SOUP_LIBS)                                    \
        $(PACKAGEKIT_LIBS)                              \
        $(GNOME_DESKTOP_LIBS)                           \
+       $(POLKIT_LIBS)                                  \
        -lm
 
 gnome_software_CFLAGS =                                        \
diff --git a/src/gs-application.c b/src/gs-application.c
index 2dc2ba0..02ed606 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+#include <gio/gio.h>
 #include <gio/gdesktopappinfo.h>
 #include <packagekit-glib2/packagekit.h>
 
@@ -46,6 +47,7 @@
 #include "gs-shell-search-provider.h"
 #include "gs-offline-updates.h"
 #include "gs-folders.h"
+#include "gs-utils.h"
 
 
 struct _GsApplication {
@@ -96,7 +98,8 @@ download_updates_setting_changed (GSettings     *settings,
                                  const gchar   *key,
                                  GsApplication *app)
 {
-       if (g_settings_get_boolean (settings, key)) {
+       if (!gs_updates_are_managed () &&
+           g_settings_get_boolean (settings, key)) {
                g_debug ("Enabling update monitor");
                app->update_monitor = gs_update_monitor_new (app);
        } else {
@@ -106,6 +109,27 @@ download_updates_setting_changed (GSettings     *settings,
 }
 
 static void
+on_permission_changed (GPermission *permission,
+                       GParamSpec  *pspec,
+                       gpointer     data)
+{
+       GsApplication *app = data;
+
+       if (app->settings)
+               download_updates_setting_changed (app->settings, "download-updates", app);
+}
+
+static void
+gs_application_monitor_permission (GsApplication *app)
+{
+       GPermission *permission;
+
+       permission = gs_offline_updates_permission_get ();
+       g_signal_connect (permission, "notify",
+                         G_CALLBACK (on_permission_changed), app);
+}
+
+static void
 gs_application_monitor_updates (GsApplication *app)
 {
        g_signal_connect (app->settings, "changed::download-updates",
@@ -510,6 +534,7 @@ gs_application_startup (GApplication *application)
        GS_APPLICATION (application)->proxy_settings = gs_proxy_settings_new ();
        GS_APPLICATION (application)->dbus_helper = gs_dbus_helper_new ();
        GS_APPLICATION (application)->settings = g_settings_new ("org.gnome.software");
+       gs_application_monitor_permission (GS_APPLICATION (application));
        gs_application_monitor_updates (GS_APPLICATION (application));
        gs_application_provide_search (GS_APPLICATION (application));
        gs_application_monitor_network (GS_APPLICATION (application));
diff --git a/src/gs-offline-updates.c b/src/gs-offline-updates.c
index 2dbf667..248da86 100644
--- a/src/gs-offline-updates.c
+++ b/src/gs-offline-updates.c
@@ -23,6 +23,7 @@
 
 #include <glib/gi18n.h>
 #include <packagekit-glib2/packagekit.h>
+#include <polkit/polkit.h>
 #include <pango/pango-font.h>
 
 #include "gs-cleanup.h"
@@ -300,4 +301,30 @@ gs_offline_updates_show_error (void)
        }
 }
 
+GPermission *
+gs_offline_updates_permission_get (void)
+{
+       static GPermission *permission;
+
+       if (!permission)
+               permission = polkit_permission_new_sync ("org.freedesktop.packagekit.trigger-offline-update",
+                                                         NULL, NULL, NULL);
+
+       return permission;
+}
+
+gboolean
+gs_updates_are_managed (void)
+{
+       GPermission *permission;
+       gboolean managed;
+
+       permission = gs_offline_updates_permission_get ();
+       managed = !g_permission_get_allowed (permission) &&
+                  !g_permission_get_can_acquire (permission);
+
+       return managed;
+}
+
+
 /* vim: set noexpandtab: */
diff --git a/src/gs-offline-updates.h b/src/gs-offline-updates.h
index be75c2e..39d38f3 100644
--- a/src/gs-offline-updates.h
+++ b/src/gs-offline-updates.h
@@ -28,6 +28,9 @@ G_BEGIN_DECLS
 
 void     gs_offline_updates_show_error         (void);
 
+GPermission    *gs_offline_updates_permission_get      (void);
+gboolean         gs_updates_are_managed                (void);
+
 
 G_END_DECLS
 
diff --git a/src/gs-shell-updates.c b/src/gs-shell-updates.c
index 94c1805..bd346c5 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -34,6 +34,7 @@
 #include "gs-markdown.h"
 #include "gs-update-dialog.h"
 #include "gs-update-list.h"
+#include "gs-application.h"
 
 #include <gdesktop-enums.h>
 #include <langinfo.h>
@@ -44,6 +45,7 @@ typedef enum {
        GS_SHELL_UPDATES_STATE_ACTION_REFRESH_HAS_UPDATES,
        GS_SHELL_UPDATES_STATE_ACTION_GET_UPDATES,
        GS_SHELL_UPDATES_STATE_NO_UPDATES,
+       GS_SHELL_UPDATES_STATE_MANAGED,
        GS_SHELL_UPDATES_STATE_HAS_UPDATES,
        GS_SHELL_UPDATES_STATE_FAILED,
        GS_SHELL_UPDATES_STATE_LAST,
@@ -232,6 +234,7 @@ gs_shell_updates_update_ui_state (GsShellUpdates *shell_updates)
                break;
        case GS_SHELL_UPDATES_STATE_ACTION_REFRESH_HAS_UPDATES:
        case GS_SHELL_UPDATES_STATE_NO_UPDATES:
+       case GS_SHELL_UPDATES_STATE_MANAGED:
        case GS_SHELL_UPDATES_STATE_HAS_UPDATES:
        case GS_SHELL_UPDATES_STATE_FAILED:
                gs_stop_spinner (GTK_SPINNER (priv->spinner_updates));
@@ -263,6 +266,7 @@ gs_shell_updates_update_ui_state (GsShellUpdates *shell_updates)
                break;
        case GS_SHELL_UPDATES_STATE_ACTION_REFRESH_HAS_UPDATES:
        case GS_SHELL_UPDATES_STATE_NO_UPDATES:
+       case GS_SHELL_UPDATES_STATE_MANAGED:
        case GS_SHELL_UPDATES_STATE_HAS_UPDATES:
        case GS_SHELL_UPDATES_STATE_FAILED:
                break;
@@ -281,6 +285,7 @@ gs_shell_updates_update_ui_state (GsShellUpdates *shell_updates)
        case GS_SHELL_UPDATES_STATE_ACTION_REFRESH_NO_UPDATES:
        case GS_SHELL_UPDATES_STATE_ACTION_GET_UPDATES:
        case GS_SHELL_UPDATES_STATE_NO_UPDATES:
+       case GS_SHELL_UPDATES_STATE_MANAGED:
        case GS_SHELL_UPDATES_STATE_HAS_UPDATES:
        case GS_SHELL_UPDATES_STATE_STARTUP:
        case GS_SHELL_UPDATES_STATE_FAILED:
@@ -304,6 +309,7 @@ gs_shell_updates_update_ui_state (GsShellUpdates *shell_updates)
                break;
        case GS_SHELL_UPDATES_STATE_ACTION_GET_UPDATES:
        case GS_SHELL_UPDATES_STATE_STARTUP:
+       case GS_SHELL_UPDATES_STATE_MANAGED:
                widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_refresh"));
                gtk_widget_hide (widget);
                break;
@@ -337,6 +343,7 @@ gs_shell_updates_update_ui_state (GsShellUpdates *shell_updates)
        case GS_SHELL_UPDATES_STATE_ACTION_REFRESH_NO_UPDATES:
        case GS_SHELL_UPDATES_STATE_ACTION_GET_UPDATES:
        case GS_SHELL_UPDATES_STATE_NO_UPDATES:
+       case GS_SHELL_UPDATES_STATE_MANAGED:
        case GS_SHELL_UPDATES_STATE_FAILED:
                gtk_widget_hide (widget);
                break;
@@ -378,6 +385,9 @@ gs_shell_updates_update_ui_state (GsShellUpdates *shell_updates)
        case GS_SHELL_UPDATES_STATE_ACTION_REFRESH_HAS_UPDATES:
                gtk_stack_set_visible_child_name (GTK_STACK (priv->stack_updates), "view");
                break;
+       case GS_SHELL_UPDATES_STATE_MANAGED:
+               gtk_stack_set_visible_child_name (GTK_STACK (priv->stack_updates), "managed");
+               break;
        case GS_SHELL_UPDATES_STATE_FAILED:
                gtk_stack_set_visible_child_name (GTK_STACK (priv->stack_updates), "failed");
                break;
@@ -409,6 +419,8 @@ gs_shell_updates_set_state (GsShellUpdates *shell_updates,
                            GsShellUpdatesState state)
 {
        shell_updates->priv->state = state;
+       if (gs_updates_are_managed ())
+               shell_updates->priv->state = GS_SHELL_UPDATES_STATE_MANAGED;
        gs_shell_updates_update_ui_state (shell_updates);
 }
 
@@ -447,7 +459,7 @@ gs_shell_updates_get_updates_cb (GsPluginLoader *plugin_loader,
        }
 
        widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_updates_counter"));
-       if (list != NULL) {
+       if (list != NULL && !gs_updates_are_managed ()) {
                _cleanup_free_ gchar *text = NULL;
                text = g_strdup_printf ("%d", g_list_length (list));
                gtk_label_set_label (GTK_LABEL (widget), text);
@@ -900,6 +912,32 @@ gs_shell_updates_status_changed_cb (GsPluginLoader *plugin_loader,
        gs_shell_updates_update_ui_state (shell_updates);
 }
 
+static void
+on_permission_changed (GPermission *permission,
+                       GParamSpec  *pspec,
+                       gpointer     data)
+{
+        GsShellUpdates *shell_updates = data;
+        GsShellUpdatesPrivate *priv = shell_updates->priv;
+
+       if (gs_updates_are_managed()) {
+               gs_shell_updates_set_state (shell_updates, GS_SHELL_UPDATES_STATE_MANAGED);
+       }
+       else if (priv->state == GS_SHELL_UPDATES_STATE_MANAGED) {
+               gs_shell_updates_set_state (shell_updates, GS_SHELL_UPDATES_STATE_NO_UPDATES);
+       }
+}
+
+static void
+gs_shell_updates_monitor_permission (GsShellUpdates *shell_updates)
+{
+        GPermission *permission;
+
+        permission = gs_offline_updates_permission_get ();
+        g_signal_connect (permission, "notify",
+                          G_CALLBACK (on_permission_changed), shell_updates);
+}
+
 void
 gs_shell_updates_setup (GsShellUpdates *shell_updates,
                        GsShell *shell,
@@ -943,6 +981,8 @@ gs_shell_updates_setup (GsShellUpdates *shell_updates,
                          G_CALLBACK (gs_shell_updates_button_network_settings_cb),
                          shell_updates);
 
+       gs_shell_updates_monitor_permission (shell_updates);
+
        g_signal_connect (priv->control, "notify::network-state",
                          G_CALLBACK (gs_shell_updates_notify_network_state_cb),
                          shell_updates);
diff --git a/src/gs-shell-updates.ui b/src/gs-shell-updates.ui
index d514d24..890983d 100644
--- a/src/gs-shell-updates.ui
+++ b/src/gs-shell-updates.ui
@@ -280,6 +280,43 @@
             <property name="name">failed</property>
           </packing>
         </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">12</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="pixel_size">128</property>
+                <property name="icon_name">action-unavailable-symbolic</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="wrap">True</property>
+                <property name="max-width-chars">60</property>
+                <property name="label" translatable="No">Updates are automatically managed</property>
+                <attributes>
+                  <attribute name="scale" value="1.4"/>
+                </attributes>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="name">managed</property>
+          </packing>
+        </child>
       </object>
     </child>
   </template>
diff --git a/src/gs-shell.c b/src/gs-shell.c
index ca9c2a1..779fc37 100644
--- a/src/gs-shell.c
+++ b/src/gs-shell.c
@@ -37,6 +37,7 @@
 #include "gs-shell-extras.h"
 #include "gs-sources-dialog.h"
 #include "gs-update-dialog.h"
+#include "gs-offline-updates.h"
 
 static const gchar *page_name[] = {
        "overview",
@@ -172,6 +173,8 @@ gs_shell_change_mode (GsShell *shell,
 
        widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_updates"));
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), mode == GS_SHELL_MODE_UPDATES);
+       gtk_widget_set_visible (widget, !gs_updates_are_managed() || mode == GS_SHELL_MODE_UPDATES);
+
        priv->ignore_primary_buttons = FALSE;
 
        /* switch page */
@@ -517,6 +520,29 @@ gs_shell_main_window_mapped_cb (GtkWidget *widget, GsShell *shell)
                                    gtk_widget_get_scale_factor (widget));
 }
 
+static void
+on_permission_changed (GPermission *permission,
+                       GParamSpec  *pspec,
+                       gpointer     data)
+{
+        GsShell *shell = data;
+       GsShellPrivate *priv = shell->priv;
+       GtkWidget *widget;
+
+       widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_updates"));
+       gtk_widget_set_visible (widget, !gs_updates_are_managed() || priv->mode == GS_SHELL_MODE_UPDATES);
+}
+
+static void
+gs_shell_monitor_permission (GsShell *shell)
+{
+        GPermission *permission;
+
+        permission = gs_offline_updates_permission_get ();
+        g_signal_connect (permission, "notify",
+                          G_CALLBACK (on_permission_changed), shell);
+}
+
 /**
  * gs_shell_setup:
  */
@@ -533,6 +559,8 @@ gs_shell_setup (GsShell *shell, GsPluginLoader *plugin_loader, GCancellable *can
                          G_CALLBACK (gs_shell_updates_changed_cb), shell);
        priv->cancellable = g_object_ref (cancellable);
 
+       gs_shell_monitor_permission (shell);
+
        /* get UI */
        priv->builder = gtk_builder_new_from_resource ("/org/gnome/Software/gnome-software.ui");
        priv->main_window = GTK_WINDOW (gtk_builder_get_object (priv->builder, "window_software"));


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