gtkappchooseronlinepk.c 8.48 KB
Newer Older
1
/*
2
 * gtkappchooseronlinepk.c: packagekit module for app-chooser
3 4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 * 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
Javier Jardón's avatar
Javier Jardón committed
17
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 19 20 21
 *
 * Authors: Cosimo Cecchi <ccecchi@redhat.com>
 */

Matthias Clasen's avatar
Matthias Clasen committed
22
#include "config.h"
23

24
#include "gtkappchooseronlinepk.h"
25

26
#include "gtkappchooseronline.h"
Matthias Clasen's avatar
Matthias Clasen committed
27
#ifdef GDK_WINDOWING_X11
28
#include "x11/gdkx.h"
Matthias Clasen's avatar
Matthias Clasen committed
29
#endif
30 31 32

#include <gio/gio.h>

33 34
#define gtk_app_chooser_online_pk_get_type _gtk_app_chooser_online_pk_get_type
static void app_chooser_online_iface_init (GtkAppChooserOnlineInterface *iface);
35
static void app_chooser_online_pk_async_initable_init (GAsyncInitableIface *iface);
36

37
G_DEFINE_TYPE_WITH_CODE (GtkAppChooserOnlinePk, gtk_app_chooser_online_pk,
Matthias Clasen's avatar
Matthias Clasen committed
38
                         G_TYPE_OBJECT,
39 40
                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
                                                app_chooser_online_pk_async_initable_init)
Matthias Clasen's avatar
Matthias Clasen committed
41 42 43 44 45
                         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));
46

47
struct _GtkAppChooserOnlinePkPrivate {
48 49 50 51
  GSimpleAsyncResult *init_result;
  guint watch_id;

  GDBusProxy *proxy;
52 53 54 55 56
  GSimpleAsyncResult *result;
  GtkWindow *parent;
};

static void
57
gtk_app_chooser_online_pk_dispose (GObject *obj)
58
{
59
  GtkAppChooserOnlinePk *self = GTK_APP_CHOOSER_ONLINE_PK (obj);
60 61

  g_clear_object (&self->priv->result);
62
  g_clear_object (&self->priv->proxy);
63

64
  G_OBJECT_CLASS (gtk_app_chooser_online_pk_parent_class)->dispose (obj);
65 66 67
}

static void
68
gtk_app_chooser_online_pk_class_init (GtkAppChooserOnlinePkClass *klass)
69 70 71
{
  GObjectClass *oclass = G_OBJECT_CLASS (klass);

72
  oclass->dispose = gtk_app_chooser_online_pk_dispose;
73

74
  g_type_class_add_private (klass, sizeof (GtkAppChooserOnlinePkPrivate));
75 76 77
}

static void
78
gtk_app_chooser_online_pk_init (GtkAppChooserOnlinePk *self)
79
{
80
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_APP_CHOOSER_ONLINE_PK,
Matthias Clasen's avatar
Matthias Clasen committed
81
                                            GtkAppChooserOnlinePkPrivate);
82 83 84
}

static gboolean
85
pk_search_mime_finish (GtkAppChooserOnline *obj,
Matthias Clasen's avatar
Matthias Clasen committed
86 87
                       GAsyncResult *res,
                       GError **error)
88 89 90 91 92 93 94
{
  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);

  return !g_simple_async_result_propagate_error (simple, error);
}

static void
Matthias Clasen's avatar
Matthias Clasen committed
95 96 97
install_mime_types_ready_cb (GObject      *source,
                             GAsyncResult *res,
                             gpointer      user_data)
98
{
99
  GtkAppChooserOnlinePk *self = user_data;
100 101 102 103 104 105
  GDBusProxy *proxy = G_DBUS_PROXY (source);
  GError *error = NULL;
  GVariant *variant;

  variant = g_dbus_proxy_call_finish (proxy, res, &error);

Matthias Clasen's avatar
Matthias Clasen committed
106 107 108 109 110 111 112 113
  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);
114

Matthias Clasen's avatar
Matthias Clasen committed
115 116
      g_error_free (error);
    }
117 118

  g_simple_async_result_complete (self->priv->result);
119
  g_clear_object (&self->priv->result);
120 121 122
}

static void
123 124 125
pk_search_mime_async (GtkAppChooserOnline *obj,
                      const gchar         *content_type,
                      GtkWindow           *parent,
126
                      GCancellable        *cancellable,
127 128
                      GAsyncReadyCallback  callback,
                      gpointer             user_data)
129
{
130
  GtkAppChooserOnlinePk *self = GTK_APP_CHOOSER_ONLINE_PK (obj);
131 132 133 134
  guint xid = 0;
  GdkWindow *window;
  const gchar *mime_types[2];

135 136
  self->priv->result = g_simple_async_result_new (G_OBJECT (self),
                                                  callback, user_data,
137
                                                  _gtk_app_chooser_online_search_for_mimetype_async);
138

Matthias Clasen's avatar
Matthias Clasen committed
139
#ifdef GDK_WINDOWING_X11
140
  window = gtk_widget_get_window (GTK_WIDGET (parent));
141
  xid = GDK_WINDOW_XID (window);
Matthias Clasen's avatar
Matthias Clasen committed
142
#endif
143

144
  mime_types[0] = content_type;
145 146
  mime_types[1] = NULL;

147
  g_dbus_proxy_call (self->priv->proxy,
Matthias Clasen's avatar
Matthias Clasen committed
148 149 150 151 152 153 154
                     "InstallMimeTypes",
                     g_variant_new ("(u^ass)",
                                    xid,
                                    mime_types,
                                    "hide-confirm-search"),
                     G_DBUS_CALL_FLAGS_NONE,
                     G_MAXINT, /* no timeout */
155
                     cancellable,
Matthias Clasen's avatar
Matthias Clasen committed
156 157
                     install_mime_types_ready_cb,
                     self);
158 159 160
}

static void
161
app_chooser_online_iface_init (GtkAppChooserOnlineInterface *iface)
162
{
163 164 165
  iface->search_for_mimetype_async = pk_search_mime_async;
  iface->search_for_mimetype_finish = pk_search_mime_finish;
}
166

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
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);
189 190 191
}

static void
192 193 194 195
pk_appeared_cb (GDBusConnection *conn,
                const gchar *name,
                const gchar *owner,
                gpointer user_data)
196
{
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
  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,
246
                                                       _gtk_app_chooser_online_get_default_async);
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262

  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;
263
}