So that we can cancel it when the dialog is destroyed. https://bugzilla.gnome.org/show_bug.cgi?id=651818
		
			
				
	
	
		
			265 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * gtkappchooseronlinepk.c: packagekit module for app-chooser
 | 
						|
 *
 | 
						|
 * Copyright (C) 2010 Red Hat, Inc.
 | 
						|
 *
 | 
						|
 * This library is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU Library General Public License as
 | 
						|
 * published by the Free Software Foundation; either version 2 of the
 | 
						|
 * License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This library 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
 | 
						|
 * Library General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU Library General Public
 | 
						|
 * License along with the Gnome Library; see the file COPYING.LIB.  If not,
 | 
						|
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 | 
						|
 * Boston, MA 02111-1307, USA.
 | 
						|
 *
 | 
						|
 * Authors: Cosimo Cecchi <ccecchi@redhat.com>
 | 
						|
 */
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
 | 
						|
#include "gtkappchooseronlinepk.h"
 | 
						|
 | 
						|
#include "gtkappchooseronline.h"
 | 
						|
#ifdef GDK_WINDOWING_X11
 | 
						|
#include "x11/gdkx.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#include <gio/gio.h>
 | 
						|
 | 
						|
#define gtk_app_chooser_online_pk_get_type _gtk_app_chooser_online_pk_get_type
 | 
						|
static void app_chooser_online_iface_init (GtkAppChooserOnlineInterface *iface);
 | 
						|
static void app_chooser_online_pk_async_initable_init (GAsyncInitableIface *iface);
 | 
						|
 | 
						|
G_DEFINE_TYPE_WITH_CODE (GtkAppChooserOnlinePk, gtk_app_chooser_online_pk,
 | 
						|
                         G_TYPE_OBJECT,
 | 
						|
                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
 | 
						|
                                                app_chooser_online_pk_async_initable_init)
 | 
						|
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER_ONLINE,
 | 
						|
                                                app_chooser_online_iface_init)
 | 
						|
                         g_io_extension_point_implement ("gtkappchooser-online",
 | 
						|
                                                         g_define_type_id,
 | 
						|
                                                         "packagekit", 10));
 | 
						|
 | 
						|
struct _GtkAppChooserOnlinePkPrivate {
 | 
						|
  GSimpleAsyncResult *init_result;
 | 
						|
  guint watch_id;
 | 
						|
 | 
						|
  GDBusProxy *proxy;
 | 
						|
  GSimpleAsyncResult *result;
 | 
						|
  GtkWindow *parent;
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
gtk_app_chooser_online_pk_dispose (GObject *obj)
 | 
						|
{
 | 
						|
  GtkAppChooserOnlinePk *self = GTK_APP_CHOOSER_ONLINE_PK (obj);
 | 
						|
 | 
						|
  g_clear_object (&self->priv->result);
 | 
						|
  g_clear_object (&self->priv->proxy);
 | 
						|
 | 
						|
  G_OBJECT_CLASS (gtk_app_chooser_online_pk_parent_class)->dispose (obj);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gtk_app_chooser_online_pk_class_init (GtkAppChooserOnlinePkClass *klass)
 | 
						|
{
 | 
						|
  GObjectClass *oclass = G_OBJECT_CLASS (klass);
 | 
						|
 | 
						|
  oclass->dispose = gtk_app_chooser_online_pk_dispose;
 | 
						|
 | 
						|
  g_type_class_add_private (klass, sizeof (GtkAppChooserOnlinePkPrivate));
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gtk_app_chooser_online_pk_init (GtkAppChooserOnlinePk *self)
 | 
						|
{
 | 
						|
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_APP_CHOOSER_ONLINE_PK,
 | 
						|
                                            GtkAppChooserOnlinePkPrivate);
 | 
						|
}
 | 
						|
 | 
						|
static gboolean
 | 
						|
pk_search_mime_finish (GtkAppChooserOnline *obj,
 | 
						|
                       GAsyncResult *res,
 | 
						|
                       GError **error)
 | 
						|
{
 | 
						|
  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
 | 
						|
 | 
						|
  return !g_simple_async_result_propagate_error (simple, error);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
install_mime_types_ready_cb (GObject      *source,
 | 
						|
                             GAsyncResult *res,
 | 
						|
                             gpointer      user_data)
 | 
						|
{
 | 
						|
  GtkAppChooserOnlinePk *self = user_data;
 | 
						|
  GDBusProxy *proxy = G_DBUS_PROXY (source);
 | 
						|
  GError *error = NULL;
 | 
						|
  GVariant *variant;
 | 
						|
 | 
						|
  variant = g_dbus_proxy_call_finish (proxy, res, &error);
 | 
						|
 | 
						|
  if (variant == NULL)
 | 
						|
    {
 | 
						|
      /* don't show errors if the user cancelled the installation explicitely
 | 
						|
       * or if PK wasn't able to find any apps
 | 
						|
       */
 | 
						|
      if (g_strcmp0 (g_dbus_error_get_remote_error (error), "org.freedesktop.PackageKit.Modify.Cancelled") != 0 &&
 | 
						|
          g_strcmp0 (g_dbus_error_get_remote_error (error), "org.freedesktop.PackageKit.Modify.NoPackagesFound") != 0)
 | 
						|
        g_simple_async_result_set_from_error (self->priv->result, error);
 | 
						|
 | 
						|
      g_error_free (error);
 | 
						|
    }
 | 
						|
 | 
						|
  g_simple_async_result_complete (self->priv->result);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
pk_search_mime_async (GtkAppChooserOnline *obj,
 | 
						|
                      const gchar         *content_type,
 | 
						|
                      GtkWindow           *parent,
 | 
						|
                      GCancellable        *cancellable,
 | 
						|
                      GAsyncReadyCallback  callback,
 | 
						|
                      gpointer             user_data)
 | 
						|
{
 | 
						|
  GtkAppChooserOnlinePk *self = GTK_APP_CHOOSER_ONLINE_PK (obj);
 | 
						|
  guint xid = 0;
 | 
						|
  GdkWindow *window;
 | 
						|
  const gchar *mime_types[2];
 | 
						|
 | 
						|
  self->priv->result = g_simple_async_result_new (G_OBJECT (self),
 | 
						|
                                                  callback, user_data,
 | 
						|
                                                  _gtk_app_chooser_online_search_for_mimetype_async);
 | 
						|
 | 
						|
#ifdef GDK_WINDOWING_X11
 | 
						|
  window = gtk_widget_get_window (GTK_WIDGET (parent));
 | 
						|
  xid = GDK_WINDOW_XID (window);
 | 
						|
#endif
 | 
						|
 | 
						|
  mime_types[0] = content_type;
 | 
						|
  mime_types[1] = NULL;
 | 
						|
 | 
						|
  g_dbus_proxy_call (self->priv->proxy,
 | 
						|
                     "InstallMimeTypes",
 | 
						|
                     g_variant_new ("(u^ass)",
 | 
						|
                                    xid,
 | 
						|
                                    mime_types,
 | 
						|
                                    "hide-confirm-search"),
 | 
						|
                     G_DBUS_CALL_FLAGS_NONE,
 | 
						|
                     G_MAXINT, /* no timeout */
 | 
						|
                     cancellable,
 | 
						|
                     install_mime_types_ready_cb,
 | 
						|
                     self);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
app_chooser_online_iface_init (GtkAppChooserOnlineInterface *iface)
 | 
						|
{
 | 
						|
  iface->search_for_mimetype_async = pk_search_mime_async;
 | 
						|
  iface->search_for_mimetype_finish = pk_search_mime_finish;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
pk_proxy_created_cb (GObject *source,
 | 
						|
                     GAsyncResult *result,
 | 
						|
                     gpointer user_data)
 | 
						|
{
 | 
						|
  GtkAppChooserOnlinePk *self = user_data;
 | 
						|
  GDBusProxy *proxy;
 | 
						|
 | 
						|
  proxy = g_dbus_proxy_new_finish (result, NULL);
 | 
						|
 | 
						|
  if (proxy == NULL)
 | 
						|
    {
 | 
						|
      g_simple_async_result_set_op_res_gboolean (self->priv->init_result, FALSE);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      g_simple_async_result_set_op_res_gboolean (self->priv->init_result, TRUE);
 | 
						|
      self->priv->proxy = proxy;
 | 
						|
    }
 | 
						|
 | 
						|
  g_simple_async_result_complete (self->priv->init_result);
 | 
						|
  g_clear_object (&self->priv->init_result);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
pk_appeared_cb (GDBusConnection *conn,
 | 
						|
                const gchar *name,
 | 
						|
                const gchar *owner,
 | 
						|
                gpointer user_data)
 | 
						|
{
 | 
						|
  GtkAppChooserOnlinePk *self = user_data;
 | 
						|
 | 
						|
  /* create the proxy */
 | 
						|
  g_dbus_proxy_new (conn, 0, NULL,
 | 
						|
                    "org.freedesktop.PackageKit",
 | 
						|
                    "/org/freedesktop/PackageKit",
 | 
						|
                    "org.freedesktop.PackageKit.Modify",
 | 
						|
                    NULL,
 | 
						|
                    pk_proxy_created_cb,
 | 
						|
                    self);
 | 
						|
 | 
						|
  g_bus_unwatch_name (self->priv->watch_id);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
pk_vanished_cb (GDBusConnection *conn,
 | 
						|
                const gchar *name,
 | 
						|
                gpointer user_data)
 | 
						|
{
 | 
						|
  GtkAppChooserOnlinePk *self = user_data;
 | 
						|
 | 
						|
  /* just return */
 | 
						|
  g_simple_async_result_set_op_res_gboolean (self->priv->init_result, FALSE);
 | 
						|
  g_simple_async_result_complete (self->priv->init_result);
 | 
						|
 | 
						|
  g_bus_unwatch_name (self->priv->watch_id);
 | 
						|
 | 
						|
  g_clear_object (&self->priv->init_result);
 | 
						|
}
 | 
						|
 | 
						|
static gboolean
 | 
						|
app_chooser_online_pk_init_finish (GAsyncInitable *init,
 | 
						|
                                   GAsyncResult *res,
 | 
						|
                                   GError **error)
 | 
						|
{
 | 
						|
  return g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (res));
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
app_chooser_online_pk_init_async (GAsyncInitable *init,
 | 
						|
                                  int io_priority,
 | 
						|
                                  GCancellable *cancellable,
 | 
						|
                                  GAsyncReadyCallback callback,
 | 
						|
                                  gpointer user_data)
 | 
						|
{
 | 
						|
  GtkAppChooserOnlinePk *self = GTK_APP_CHOOSER_ONLINE_PK (init);
 | 
						|
 | 
						|
  self->priv->init_result = g_simple_async_result_new (G_OBJECT (self),
 | 
						|
                                                       callback, user_data,
 | 
						|
                                                       _gtk_app_chooser_online_get_default_async);
 | 
						|
 | 
						|
  self->priv->watch_id =
 | 
						|
    g_bus_watch_name (G_BUS_TYPE_SESSION,
 | 
						|
                      "org.freedesktop.PackageKit",
 | 
						|
                      G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
 | 
						|
                      pk_appeared_cb,
 | 
						|
                      pk_vanished_cb,
 | 
						|
                      self,
 | 
						|
                      NULL);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
app_chooser_online_pk_async_initable_init (GAsyncInitableIface *iface)
 | 
						|
{
 | 
						|
  iface->init_async = app_chooser_online_pk_init_async;
 | 
						|
  iface->init_finish = app_chooser_online_pk_init_finish;
 | 
						|
}
 |