[gnome-software/gnome-3-16] Hide updates UI on managed systems



commit c63f6e62f40758940e7a9f851352a7c4bf16ab57
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 c4d076b..74c5871 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,6 +66,7 @@ PKG_CHECK_MODULES(SQLITE, sqlite3)
 PKG_CHECK_MODULES(SOUP, libsoup-2.4)
 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 9ca9e2d..b0c41ba 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\" \
@@ -188,6 +189,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 51fd8d5..8b8278f 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 092272b..a848507 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>
@@ -46,6 +47,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,
@@ -234,6 +236,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));
@@ -265,6 +268,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;
@@ -283,6 +287,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:
@@ -306,6 +311,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;
@@ -339,6 +345,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;
@@ -380,6 +387,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;
@@ -411,6 +421,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);
 }
 
@@ -449,7 +461,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);
@@ -879,6 +891,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,
@@ -922,6 +960,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 f04812d..bd3562a 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",
@@ -174,6 +175,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 */
@@ -519,6 +522,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:
  */
@@ -535,6 +561,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]