]> Pileus Git - ~andy/gtk/blob - gtk/gtkappchooseronlinepk.c
0f62bb2594364e704d1066a266f0ddcd4a2e317c
[~andy/gtk] / gtk / gtkappchooseronlinepk.c
1 /*
2  * gtkappchooseronlinepk.c: packagekit module for app-chooser
3  *
4  * Copyright (C) 2010 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with the Gnome Library; see the file COPYING.LIB.  If not,
18  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  * Authors: Cosimo Cecchi <ccecchi@redhat.com>
22  */
23
24 #include "config.h"
25
26 #include "gtkappchooseronlinepk.h"
27
28 #include "gtkappchooseronline.h"
29 #ifdef GDK_WINDOWING_X11
30 #include "x11/gdkx.h"
31 #endif
32
33 #include <gio/gio.h>
34
35 #define gtk_app_chooser_online_pk_get_type _gtk_app_chooser_online_pk_get_type
36 static void app_chooser_online_iface_init (GtkAppChooserOnlineInterface *iface);
37 static void app_chooser_online_pk_async_initable_init (GAsyncInitableIface *iface);
38
39 G_DEFINE_TYPE_WITH_CODE (GtkAppChooserOnlinePk, gtk_app_chooser_online_pk,
40                          G_TYPE_OBJECT,
41                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
42                                                 app_chooser_online_pk_async_initable_init)
43                          G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER_ONLINE,
44                                                 app_chooser_online_iface_init)
45                          g_io_extension_point_implement ("gtkappchooser-online",
46                                                          g_define_type_id,
47                                                          "packagekit", 10));
48
49 struct _GtkAppChooserOnlinePkPrivate {
50   GSimpleAsyncResult *init_result;
51   guint watch_id;
52
53   GDBusProxy *proxy;
54   GSimpleAsyncResult *result;
55   GtkWindow *parent;
56 };
57
58 static void
59 gtk_app_chooser_online_pk_dispose (GObject *obj)
60 {
61   GtkAppChooserOnlinePk *self = GTK_APP_CHOOSER_ONLINE_PK (obj);
62
63   g_clear_object (&self->priv->result);
64   g_clear_object (&self->priv->proxy);
65
66   G_OBJECT_CLASS (gtk_app_chooser_online_pk_parent_class)->dispose (obj);
67 }
68
69 static void
70 gtk_app_chooser_online_pk_class_init (GtkAppChooserOnlinePkClass *klass)
71 {
72   GObjectClass *oclass = G_OBJECT_CLASS (klass);
73
74   oclass->dispose = gtk_app_chooser_online_pk_dispose;
75
76   g_type_class_add_private (klass, sizeof (GtkAppChooserOnlinePkPrivate));
77 }
78
79 static void
80 gtk_app_chooser_online_pk_init (GtkAppChooserOnlinePk *self)
81 {
82   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_APP_CHOOSER_ONLINE_PK,
83                                             GtkAppChooserOnlinePkPrivate);
84 }
85
86 static gboolean
87 pk_search_mime_finish (GtkAppChooserOnline *obj,
88                        GAsyncResult *res,
89                        GError **error)
90 {
91   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
92
93   return !g_simple_async_result_propagate_error (simple, error);
94 }
95
96 static void
97 install_mime_types_ready_cb (GObject      *source,
98                              GAsyncResult *res,
99                              gpointer      user_data)
100 {
101   GtkAppChooserOnlinePk *self = user_data;
102   GDBusProxy *proxy = G_DBUS_PROXY (source);
103   GError *error = NULL;
104   GVariant *variant;
105
106   variant = g_dbus_proxy_call_finish (proxy, res, &error);
107
108   if (variant == NULL)
109     {
110       /* don't show errors if the user cancelled the installation explicitely
111        * or if PK wasn't able to find any apps
112        */
113       if (g_strcmp0 (g_dbus_error_get_remote_error (error), "org.freedesktop.PackageKit.Modify.Cancelled") != 0 &&
114           g_strcmp0 (g_dbus_error_get_remote_error (error), "org.freedesktop.PackageKit.Modify.NoPackagesFound") != 0)
115         g_simple_async_result_set_from_error (self->priv->result, error);
116
117       g_error_free (error);
118     }
119
120   g_simple_async_result_complete (self->priv->result);
121   g_clear_object (&self->priv->result);
122 }
123
124 static void
125 pk_search_mime_async (GtkAppChooserOnline *obj,
126                       const gchar         *content_type,
127                       GtkWindow           *parent,
128                       GCancellable        *cancellable,
129                       GAsyncReadyCallback  callback,
130                       gpointer             user_data)
131 {
132   GtkAppChooserOnlinePk *self = GTK_APP_CHOOSER_ONLINE_PK (obj);
133   guint xid = 0;
134   GdkWindow *window;
135   const gchar *mime_types[2];
136
137   self->priv->result = g_simple_async_result_new (G_OBJECT (self),
138                                                   callback, user_data,
139                                                   _gtk_app_chooser_online_search_for_mimetype_async);
140
141 #ifdef GDK_WINDOWING_X11
142   window = gtk_widget_get_window (GTK_WIDGET (parent));
143   xid = GDK_WINDOW_XID (window);
144 #endif
145
146   mime_types[0] = content_type;
147   mime_types[1] = NULL;
148
149   g_dbus_proxy_call (self->priv->proxy,
150                      "InstallMimeTypes",
151                      g_variant_new ("(u^ass)",
152                                     xid,
153                                     mime_types,
154                                     "hide-confirm-search"),
155                      G_DBUS_CALL_FLAGS_NONE,
156                      G_MAXINT, /* no timeout */
157                      cancellable,
158                      install_mime_types_ready_cb,
159                      self);
160 }
161
162 static void
163 app_chooser_online_iface_init (GtkAppChooserOnlineInterface *iface)
164 {
165   iface->search_for_mimetype_async = pk_search_mime_async;
166   iface->search_for_mimetype_finish = pk_search_mime_finish;
167 }
168
169 static void
170 pk_proxy_created_cb (GObject *source,
171                      GAsyncResult *result,
172                      gpointer user_data)
173 {
174   GtkAppChooserOnlinePk *self = user_data;
175   GDBusProxy *proxy;
176
177   proxy = g_dbus_proxy_new_finish (result, NULL);
178
179   if (proxy == NULL)
180     {
181       g_simple_async_result_set_op_res_gboolean (self->priv->init_result, FALSE);
182     }
183   else
184     {
185       g_simple_async_result_set_op_res_gboolean (self->priv->init_result, TRUE);
186       self->priv->proxy = proxy;
187     }
188
189   g_simple_async_result_complete (self->priv->init_result);
190   g_clear_object (&self->priv->init_result);
191 }
192
193 static void
194 pk_appeared_cb (GDBusConnection *conn,
195                 const gchar *name,
196                 const gchar *owner,
197                 gpointer user_data)
198 {
199   GtkAppChooserOnlinePk *self = user_data;
200
201   /* create the proxy */
202   g_dbus_proxy_new (conn, 0, NULL,
203                     "org.freedesktop.PackageKit",
204                     "/org/freedesktop/PackageKit",
205                     "org.freedesktop.PackageKit.Modify",
206                     NULL,
207                     pk_proxy_created_cb,
208                     self);
209
210   g_bus_unwatch_name (self->priv->watch_id);
211 }
212
213 static void
214 pk_vanished_cb (GDBusConnection *conn,
215                 const gchar *name,
216                 gpointer user_data)
217 {
218   GtkAppChooserOnlinePk *self = user_data;
219
220   /* just return */
221   g_simple_async_result_set_op_res_gboolean (self->priv->init_result, FALSE);
222   g_simple_async_result_complete (self->priv->init_result);
223
224   g_bus_unwatch_name (self->priv->watch_id);
225
226   g_clear_object (&self->priv->init_result);
227 }
228
229 static gboolean
230 app_chooser_online_pk_init_finish (GAsyncInitable *init,
231                                    GAsyncResult *res,
232                                    GError **error)
233 {
234   return g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (res));
235 }
236
237 static void
238 app_chooser_online_pk_init_async (GAsyncInitable *init,
239                                   int io_priority,
240                                   GCancellable *cancellable,
241                                   GAsyncReadyCallback callback,
242                                   gpointer user_data)
243 {
244   GtkAppChooserOnlinePk *self = GTK_APP_CHOOSER_ONLINE_PK (init);
245
246   self->priv->init_result = g_simple_async_result_new (G_OBJECT (self),
247                                                        callback, user_data,
248                                                        _gtk_app_chooser_online_get_default_async);
249
250   self->priv->watch_id =
251     g_bus_watch_name (G_BUS_TYPE_SESSION,
252                       "org.freedesktop.PackageKit",
253                       G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
254                       pk_appeared_cb,
255                       pk_vanished_cb,
256                       self,
257                       NULL);
258 }
259
260 static void
261 app_chooser_online_pk_async_initable_init (GAsyncInitableIface *iface)
262 {
263   iface->init_async = app_chooser_online_pk_init_async;
264   iface->init_finish = app_chooser_online_pk_init_finish;
265 }