~ctf/unity-settings-daemon/bug1389099_mic_volume_icons

« back to all changes in this revision

Viewing changes to plugins/updates/gsd-updates-manager.c

  • Committer: Package Import Robot
  • Author(s): Robert Ancell
  • Date: 2014-02-07 11:44:36 UTC
  • Revision ID: package-import@ubuntu.com-20140207114436-7t5u3yvwc4ul7w3e
Tags: upstream-14.04.0
ImportĀ upstreamĀ versionĀ 14.04.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2011 Richard Hughes <richard@hughsie.com>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
 
 
23
#include <locale.h>
 
24
 
 
25
#include <glib.h>
 
26
#include <glib/gi18n.h>
 
27
#include <gtk/gtk.h>
 
28
#include <packagekit-glib2/packagekit.h>
 
29
#include <libnotify/notify.h>
 
30
#include <gdesktop-enums.h>
 
31
 
 
32
#include "gsd-enums.h"
 
33
#include "gsd-updates-manager.h"
 
34
#include "gsd-updates-firmware.h"
 
35
#include "gsd-updates-refresh.h"
 
36
#include "gsd-updates-common.h"
 
37
#include "gnome-settings-profile.h"
 
38
#include "gnome-settings-session.h"
 
39
 
 
40
#define GSD_UPDATES_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_UPDATES_MANAGER, GsdUpdatesManagerPrivate))
 
41
 
 
42
#define MAX_FAILED_GET_UPDATES              10 /* the maximum number of tries */
 
43
#define GSD_UPDATES_ICON_NORMAL             "software-update-available-symbolic"
 
44
#define GSD_UPDATES_ICON_URGENT             "software-update-urgent-symbolic"
 
45
#define GSD_UPDATES_CHECK_OFFLINE_TIMEOUT   30 /* time in seconds */
 
46
 
 
47
struct GsdUpdatesManagerPrivate
 
48
{
 
49
        GCancellable            *cancellable;
 
50
        GsdUpdatesRefresh       *refresh;
 
51
        GsdUpdatesFirmware      *firmware;
 
52
        GSettings               *settings_proxy;
 
53
        GSettings               *settings_ftp;
 
54
        GSettings               *settings_gsd;
 
55
        GSettings               *settings_http;
 
56
        guint                    number_updates_critical_last_shown;
 
57
        guint                    offline_update_id;
 
58
        PkError                 *offline_update_error;
 
59
        NotifyNotification      *notification_updates;
 
60
        PkControl               *control;
 
61
        PkTask                  *task;
 
62
        guint                    inhibit_cookie;
 
63
        GDBusProxy              *proxy_session;
 
64
        guint                    update_viewer_watcher_id;
 
65
        GVolumeMonitor          *volume_monitor;
 
66
        guint                    failed_get_updates_count;
 
67
        GPtrArray               *update_packages;
 
68
};
 
69
 
 
70
static void gsd_updates_manager_class_init (GsdUpdatesManagerClass *klass);
 
71
static void gsd_updates_manager_init (GsdUpdatesManager *updates_manager);
 
72
 
 
73
G_DEFINE_TYPE (GsdUpdatesManager, gsd_updates_manager, G_TYPE_OBJECT)
 
74
 
 
75
static gpointer manager_object = NULL;
 
76
 
 
77
static void
 
78
child_exit_cb (GPid pid, gint status, gpointer user_data)
 
79
{
 
80
        g_spawn_close_pid (pid);
 
81
}
 
82
 
 
83
static void
 
84
clear_offline_updates_message (void)
 
85
{
 
86
        gboolean ret;
 
87
        GError *error = NULL;
 
88
        gchar *argv[3];
 
89
        GPid pid;
 
90
 
 
91
        argv[0] = "pkexec";
 
92
        argv[1] = LIBEXECDIR "/pk-clear-offline-update";
 
93
        argv[2] = NULL;
 
94
        ret = g_spawn_async (NULL,
 
95
                             argv,
 
96
                             NULL,
 
97
                             G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
 
98
                             NULL,
 
99
                             NULL,
 
100
                             &pid,
 
101
                             &error);
 
102
        if (!ret) {
 
103
                g_warning ("Failure clearing offline update message: %s",
 
104
                           error->message);
 
105
                g_error_free (error);
 
106
                return;
 
107
        }
 
108
        g_child_watch_add (pid, child_exit_cb, NULL);
 
109
}
 
110
 
 
111
static void
 
112
show_offline_updates_error (GsdUpdatesManager *manager)
 
113
{
 
114
        const gchar *title;
 
115
        gboolean show_geeky = FALSE;
 
116
        GString *msg;
 
117
        GtkWidget *dialog;
 
118
 
 
119
        /* TRANSLATORS: this is when the offline update failed */
 
120
        title = _("Failed To Update");
 
121
        msg = g_string_new ("");
 
122
        switch (pk_error_get_code (manager->priv->offline_update_error)) {
 
123
        case PK_ERROR_ENUM_UNFINISHED_TRANSACTION:
 
124
                /* TRANSLATORS: the transaction could not be completed
 
125
                 * as a previous transaction was unfinished */
 
126
                g_string_append (msg, _("A previous update was unfinished."));
 
127
                show_geeky = TRUE;
 
128
                break;
 
129
        case PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED:
 
130
        case PK_ERROR_ENUM_NO_CACHE:
 
131
        case PK_ERROR_ENUM_NO_NETWORK:
 
132
        case PK_ERROR_ENUM_NO_MORE_MIRRORS_TO_TRY:
 
133
        case PK_ERROR_ENUM_CANNOT_FETCH_SOURCES:
 
134
                /* TRANSLATORS: the package manager needed to download
 
135
                 * something with no network available */
 
136
                g_string_append (msg, _("Network access was required but not available."));
 
137
                break;
 
138
        case PK_ERROR_ENUM_BAD_GPG_SIGNATURE:
 
139
        case PK_ERROR_ENUM_CANNOT_UPDATE_REPO_UNSIGNED:
 
140
        case PK_ERROR_ENUM_GPG_FAILURE:
 
141
        case PK_ERROR_ENUM_MISSING_GPG_SIGNATURE:
 
142
        case PK_ERROR_ENUM_PACKAGE_CORRUPT:
 
143
                /* TRANSLATORS: if the package is not signed correctly
 
144
                 *  */
 
145
                g_string_append (msg, _("An update was not signed in the correct way."));
 
146
                show_geeky = TRUE;
 
147
                break;
 
148
        case PK_ERROR_ENUM_DEP_RESOLUTION_FAILED:
 
149
        case PK_ERROR_ENUM_FILE_CONFLICTS:
 
150
        case PK_ERROR_ENUM_INCOMPATIBLE_ARCHITECTURE:
 
151
        case PK_ERROR_ENUM_PACKAGE_CONFLICTS:
 
152
                /* TRANSLATORS: the transaction failed in a way the user
 
153
                 * probably cannot comprehend. Package management systems
 
154
                 * really are teh suck.*/
 
155
                g_string_append (msg, _("The update could not be completed."));
 
156
                show_geeky = TRUE;
 
157
                break;
 
158
        case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
 
159
                /* TRANSLATORS: the user aborted the update manually */
 
160
                g_string_append (msg, _("The update was cancelled."));
 
161
                break;
 
162
        case PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE:
 
163
        case PK_ERROR_ENUM_UPDATE_NOT_FOUND:
 
164
                /* TRANSLATORS: the user must have updated manually after
 
165
                 * the updates were prepared */
 
166
                g_string_append (msg, _("An offline update was requested but no packages required updating."));
 
167
                break;
 
168
        case PK_ERROR_ENUM_NO_SPACE_ON_DEVICE:
 
169
                /* TRANSLATORS: we ran out of disk space */
 
170
                g_string_append (msg, _("No space was left on the drive."));
 
171
                break;
 
172
        case PK_ERROR_ENUM_PACKAGE_FAILED_TO_BUILD:
 
173
        case PK_ERROR_ENUM_PACKAGE_FAILED_TO_INSTALL:
 
174
        case PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE:
 
175
                /* TRANSLATORS: the update process failed in a general
 
176
                 * way, usually this message will come from source distros
 
177
                 * like gentoo */
 
178
                g_string_append (msg, _("An update failed to install correctly."));
 
179
                show_geeky = TRUE;
 
180
                break;
 
181
        default:
 
182
                /* TRANSLATORS: We didn't handle the error type */
 
183
                g_string_append (msg, _("The offline update failed in an unexpected way."));
 
184
                show_geeky = TRUE;
 
185
                break;
 
186
        }
 
187
        if (show_geeky) {
 
188
                g_string_append_printf (msg, "\n%s\n\n%s",
 
189
                                        /* TRANSLATORS: these are geeky messages from the
 
190
                                         * package manager no mortal is supposed to understand,
 
191
                                         * but google might know what they mean */
 
192
                                        _("Detailed errors from the package manager follow:"),
 
193
                                        pk_error_get_details (manager->priv->offline_update_error));
 
194
        }
 
195
        dialog = gtk_message_dialog_new (NULL,
 
196
                                         0,
 
197
                                         GTK_MESSAGE_INFO,
 
198
                                         GTK_BUTTONS_CLOSE,
 
199
                                         "%s", title);
 
200
        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
 
201
                                                  "%s", msg->str);
 
202
        g_signal_connect_swapped (dialog, "response",
 
203
                                  G_CALLBACK (gtk_widget_destroy),
 
204
                                  dialog);
 
205
        gtk_widget_show (dialog);
 
206
        clear_offline_updates_message ();
 
207
        g_string_free (msg, TRUE);
 
208
}
 
209
 
 
210
static void
 
211
libnotify_action_cb (NotifyNotification *notification,
 
212
                     gchar *action,
 
213
                     gpointer user_data)
 
214
{
 
215
        gboolean ret;
 
216
        GError *error = NULL;
 
217
        GsdUpdatesManager *manager = GSD_UPDATES_MANAGER (user_data);
 
218
 
 
219
        notify_notification_close (notification, NULL);
 
220
        if (g_strcmp0 (action, "distro-upgrade-info") == 0) {
 
221
                ret = g_spawn_command_line_async (DATADIR "/PackageKit/pk-upgrade-distro.sh",
 
222
                                                  &error);
 
223
                if (!ret) {
 
224
                        g_warning ("Failure launching pk-upgrade-distro.sh: %s",
 
225
                                   error->message);
 
226
                        g_error_free (error);
 
227
                }
 
228
                goto out;
 
229
        }
 
230
        if (g_strcmp0 (action, "show-update-viewer") == 0) {
 
231
                ret = g_spawn_command_line_async (BINDIR "/gpk-update-viewer",
 
232
                                                  &error);
 
233
                if (!ret) {
 
234
                        g_warning ("Failure launching update viewer: %s",
 
235
                                   error->message);
 
236
                        g_error_free (error);
 
237
                }
 
238
                goto out;
 
239
        }
 
240
        if (g_strcmp0 (action, "clear-offline-updates") == 0) {
 
241
                clear_offline_updates_message ();
 
242
                goto out;
 
243
        }
 
244
        if (g_strcmp0 (action, "error-offline-updates") == 0) {
 
245
                show_offline_updates_error (manager);
 
246
                goto out;
 
247
        }
 
248
        if (g_strcmp0 (action, "cancel") == 0) {
 
249
                /* try to cancel */
 
250
                g_cancellable_cancel (manager->priv->cancellable);
 
251
                goto out;
 
252
        }
 
253
        g_warning ("unknown action id: %s", action);
 
254
out:
 
255
        return;
 
256
}
 
257
 
 
258
static void
 
259
on_notification_closed (NotifyNotification *notification, gpointer data)
 
260
{
 
261
        g_object_unref (notification);
 
262
}
 
263
 
 
264
static void
 
265
get_distro_upgrades_finished_cb (GObject *object,
 
266
                                 GAsyncResult *res,
 
267
                                 GsdUpdatesManager *manager)
 
268
{
 
269
        const gchar *title;
 
270
        gboolean ret;
 
271
        gchar *name = NULL;
 
272
        GError *error = NULL;
 
273
        GPtrArray *array = NULL;
 
274
        GString *string = NULL;
 
275
        guint i;
 
276
        NotifyNotification *notification;
 
277
        PkClient *client = PK_CLIENT(object);
 
278
        PkDistroUpgrade *item;
 
279
        PkError *error_code = NULL;
 
280
        PkResults *results;
 
281
        PkUpdateStateEnum state;
 
282
 
 
283
        /* get the results */
 
284
        results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
 
285
        if (results == NULL) {
 
286
                if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
 
287
                        g_error_free (error);
 
288
                        return;
 
289
                }
 
290
                if (error->domain != PK_CLIENT_ERROR ||
 
291
                    error->code != PK_CLIENT_ERROR_NOT_SUPPORTED) {
 
292
                        g_warning ("failed to get upgrades: %s",
 
293
                                   error->message);
 
294
                }
 
295
                g_error_free (error);
 
296
                goto out;
 
297
        }
 
298
 
 
299
        /* check error code */
 
300
        error_code = pk_results_get_error_code (results);
 
301
        if (error_code != NULL) {
 
302
                g_warning ("failed to get upgrades: %s, %s",
 
303
                           pk_error_enum_to_string (pk_error_get_code (error_code)),
 
304
                           pk_error_get_details (error_code));
 
305
                goto out;
 
306
        }
 
307
 
 
308
        /* process results */
 
309
        array = pk_results_get_distro_upgrade_array (results);
 
310
 
 
311
        /* any updates? */
 
312
        if (array->len == 0) {
 
313
                g_debug ("no upgrades");
 
314
                goto out;
 
315
        }
 
316
 
 
317
        /* do we do the notification? */
 
318
        ret = g_settings_get_boolean (manager->priv->settings_gsd,
 
319
                                      GSD_SETTINGS_NOTIFY_DISTRO_UPGRADES);
 
320
        if (!ret) {
 
321
                g_debug ("ignoring due to GSettings");
 
322
                goto out;
 
323
        }
 
324
 
 
325
        /* find the upgrade string */
 
326
        string = g_string_new ("");
 
327
        for (i=0; i < array->len; i++) {
 
328
                item = (PkDistroUpgrade *) g_ptr_array_index (array, i);
 
329
                g_object_get (item,
 
330
                              "name", &name,
 
331
                              "state", &state,
 
332
                              NULL);
 
333
                g_string_append_printf (string, "%s (%s)\n",
 
334
                                        name,
 
335
                                        pk_distro_upgrade_enum_to_string (state));
 
336
                g_free (name);
 
337
        }
 
338
        if (string->len != 0)
 
339
                g_string_set_size (string, string->len-1);
 
340
 
 
341
        /* TRANSLATORS: a distro update is available, e.g. Fedora 8 to Fedora 9 */
 
342
        title = _("Distribution upgrades available");
 
343
        notification = notify_notification_new (title,
 
344
                                                string->str,
 
345
                                                GSD_UPDATES_ICON_NORMAL);
 
346
        notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
 
347
        notify_notification_set_app_name (notification, _("Software Updates"));
 
348
        notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
 
349
        notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
 
350
        notify_notification_add_action (notification, "distro-upgrade-info",
 
351
                                        /* TRANSLATORS: provides more information about the upgrade */
 
352
                                        _("More information"),
 
353
                                        libnotify_action_cb,
 
354
                                        manager, NULL);
 
355
        g_signal_connect (notification, "closed",
 
356
                          G_CALLBACK (on_notification_closed), NULL);
 
357
        ret = notify_notification_show (notification, &error);
 
358
        if (!ret) {
 
359
                g_warning ("error: %s", error->message);
 
360
                g_error_free (error);
 
361
        }
 
362
out:
 
363
        if (error_code != NULL)
 
364
                g_object_unref (error_code);
 
365
        if (array != NULL)
 
366
                g_ptr_array_unref (array);
 
367
        if (string != NULL)
 
368
                g_string_free (string, TRUE);
 
369
        if (results != NULL)
 
370
                g_object_unref (results);
 
371
}
 
372
 
 
373
static void
 
374
due_get_upgrades_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager)
 
375
{
 
376
        /* optimize the amount of downloaded data by setting the cache age */
 
377
        pk_client_set_cache_age (PK_CLIENT(manager->priv->task),
 
378
                                 g_settings_get_int (manager->priv->settings_gsd,
 
379
                                                     GSD_SETTINGS_FREQUENCY_GET_UPGRADES));
 
380
 
 
381
        /* get new distro upgrades list */
 
382
        pk_client_get_distro_upgrades_async (PK_CLIENT(manager->priv->task),
 
383
                                             NULL,
 
384
                                             NULL, NULL,
 
385
                                             (GAsyncReadyCallback) get_distro_upgrades_finished_cb,
 
386
                                             manager);
 
387
}
 
388
 
 
389
static void
 
390
refresh_cache_finished_cb (GObject *object, GAsyncResult *res, GsdUpdatesManager *manager)
 
391
{
 
392
        PkClient *client = PK_CLIENT(object);
 
393
        PkResults *results;
 
394
        GError *error = NULL;
 
395
        PkError *error_code = NULL;
 
396
 
 
397
        /* get the results */
 
398
        results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
 
399
        if (results == NULL) {
 
400
                if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
 
401
                        g_error_free (error);
 
402
                        return;
 
403
                }
 
404
                g_warning ("failed to refresh the cache: %s",
 
405
                           error->message);
 
406
                g_error_free (error);
 
407
                return;
 
408
        }
 
409
 
 
410
        /* check error code */
 
411
        error_code = pk_results_get_error_code (results);
 
412
        if (error_code != NULL) {
 
413
                g_warning ("failed to refresh the cache: %s, %s",
 
414
                           pk_error_enum_to_string (pk_error_get_code (error_code)),
 
415
                           pk_error_get_details (error_code));
 
416
        }
 
417
 
 
418
        if (error_code != NULL)
 
419
                g_object_unref (error_code);
 
420
        if (results != NULL)
 
421
                g_object_unref (results);
 
422
}
 
423
 
 
424
static void
 
425
due_refresh_cache_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager)
 
426
{
 
427
        /* optimize the amount of downloaded data by setting the cache age */
 
428
        pk_client_set_cache_age (PK_CLIENT(manager->priv->task),
 
429
                                 g_settings_get_int (manager->priv->settings_gsd,
 
430
                                                     GSD_SETTINGS_FREQUENCY_REFRESH_CACHE));
 
431
 
 
432
        pk_client_refresh_cache_async (PK_CLIENT(manager->priv->task),
 
433
                                       TRUE,
 
434
                                       NULL,
 
435
                                       NULL, NULL,
 
436
                                       (GAsyncReadyCallback) refresh_cache_finished_cb,
 
437
                                       manager);
 
438
}
 
439
 
 
440
static void
 
441
notify_critical_updates (GsdUpdatesManager *manager, GPtrArray *array)
 
442
{
 
443
        const gchar *message;
 
444
        const gchar *title;
 
445
        gboolean ret;
 
446
        GError *error = NULL;
 
447
        NotifyNotification *notification;
 
448
 
 
449
        /* if the number of critical updates is the same as the last notification,
 
450
         * then skip the notifcation as we don't want to bombard the user every hour */
 
451
        if (array->len == manager->priv->number_updates_critical_last_shown) {
 
452
                g_debug ("ignoring as user ignored last warning");
 
453
                return;
 
454
        }
 
455
 
 
456
        /* save for comparison later */
 
457
        manager->priv->number_updates_critical_last_shown = array->len;
 
458
 
 
459
        /* TRANSLATORS: title in the libnotify popup */
 
460
        title = ngettext ("Update", "Updates", array->len);
 
461
 
 
462
        /* TRANSLATORS: message when there are security updates */
 
463
        message = ngettext ("An important software update is available",
 
464
                            "Important software updates are available", array->len);
 
465
 
 
466
        /* close any existing notification */
 
467
        if (manager->priv->notification_updates != NULL) {
 
468
                notify_notification_close (manager->priv->notification_updates, NULL);
 
469
                manager->priv->notification_updates = NULL;
 
470
        }
 
471
 
 
472
        /* do the bubble */
 
473
        g_debug ("title=%s, message=%s", title, message);
 
474
        notification = notify_notification_new (title,
 
475
                                                message,
 
476
                                                GSD_UPDATES_ICON_URGENT);
 
477
        notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
 
478
        notify_notification_set_app_name (notification, _("Software Updates"));
 
479
        notify_notification_set_timeout (notification, 15000);
 
480
        notify_notification_set_urgency (notification, NOTIFY_URGENCY_CRITICAL);
 
481
        notify_notification_add_action (notification, "show-update-viewer",
 
482
                                        /* TRANSLATORS: button: open the update viewer to install updates*/
 
483
                                        _("Install updates"), libnotify_action_cb, manager, NULL);
 
484
        g_signal_connect (notification, "closed",
 
485
                          G_CALLBACK (on_notification_closed), NULL);
 
486
        ret = notify_notification_show (notification, &error);
 
487
        if (!ret) {
 
488
                g_warning ("error: %s", error->message);
 
489
                g_error_free (error);
 
490
        }
 
491
        /* track so we can prevent doubled notifications */
 
492
        manager->priv->notification_updates = notification;
 
493
        g_object_add_weak_pointer (G_OBJECT (manager->priv->notification_updates),
 
494
                                   (void **) &manager->priv->notification_updates);
 
495
}
 
496
 
 
497
static void
 
498
notify_normal_updates_maybe (GsdUpdatesManager *manager, GPtrArray *array)
 
499
{
 
500
        const gchar *message;
 
501
        const gchar *title;
 
502
        gboolean ret;
 
503
        GError *error = NULL;
 
504
        guint64 time_last_notify;
 
505
        guint64 time_now;
 
506
        guint freq_updates_notify;
 
507
        NotifyNotification *notification;
 
508
 
 
509
        /* find out if enough time has passed since the last notification */
 
510
        time_now = g_get_real_time () / 1000000;
 
511
        freq_updates_notify = g_settings_get_int (manager->priv->settings_gsd,
 
512
                                                  GSD_SETTINGS_FREQUENCY_UPDATES_NOTIFICATION);
 
513
        g_settings_get (manager->priv->settings_gsd,
 
514
                        GSD_SETTINGS_LAST_UPDATES_NOTIFICATION,
 
515
                        "t", &time_last_notify);
 
516
        if (time_last_notify > 0 &&
 
517
            (guint64) freq_updates_notify > time_now - time_last_notify) {
 
518
                g_debug ("not showing non-critical notification as already shown %i hours ago",
 
519
                        (guint) (time_now - time_last_notify) / (60 * 60));
 
520
                return;
 
521
        }
 
522
 
 
523
        /* TRANSLATORS: title in the libnotify popup */
 
524
        title = ngettext ("Update", "Updates", array->len);
 
525
 
 
526
        /* TRANSLATORS: message when there are non-security updates */
 
527
        message = ngettext ("A software update is available.",
 
528
                            "Software updates are available.", array->len);
 
529
 
 
530
        /* close any existing notification */
 
531
        if (manager->priv->notification_updates != NULL) {
 
532
                notify_notification_close (manager->priv->notification_updates, NULL);
 
533
                manager->priv->notification_updates = NULL;
 
534
        }
 
535
 
 
536
        /* do the bubble */
 
537
        g_debug ("title=%s, message=%s", title, message);
 
538
        notification = notify_notification_new (title,
 
539
                                                message,
 
540
                                                GSD_UPDATES_ICON_NORMAL);
 
541
        notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
 
542
        notify_notification_set_app_name (notification, _("Software Updates"));
 
543
        notify_notification_set_timeout (notification, 15000);
 
544
        notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
 
545
        notify_notification_add_action (notification, "show-update-viewer",
 
546
                                        /* TRANSLATORS: button: open the update viewer to install updates*/
 
547
                                        _("Install updates"), libnotify_action_cb, manager, NULL);
 
548
        g_signal_connect (notification, "closed",
 
549
                          G_CALLBACK (on_notification_closed), NULL);
 
550
        ret = notify_notification_show (notification, &error);
 
551
        if (!ret) {
 
552
                g_warning ("error: %s", error->message);
 
553
                g_error_free (error);
 
554
        }
 
555
 
 
556
        /* reset notification time */
 
557
        g_settings_set (manager->priv->settings_gsd,
 
558
                        GSD_SETTINGS_LAST_UPDATES_NOTIFICATION,
 
559
                        "t", time_now);
 
560
 
 
561
        /* track so we can prevent doubled notifications */
 
562
        manager->priv->notification_updates = notification;
 
563
        g_object_add_weak_pointer (G_OBJECT (manager->priv->notification_updates),
 
564
                                   (void **) &manager->priv->notification_updates);
 
565
}
 
566
 
 
567
static void
 
568
notify_failed_get_updates_maybe (GsdUpdatesManager *manager)
 
569
{
 
570
        const gchar *button;
 
571
        const gchar *message;
 
572
        const gchar *title;
 
573
        gboolean ret;
 
574
        GError *error = NULL;
 
575
        NotifyNotification *notification;
 
576
 
 
577
        /* give the user a break */
 
578
        if (manager->priv->failed_get_updates_count++ < MAX_FAILED_GET_UPDATES) {
 
579
                g_debug ("failed GetUpdates, but will retry %i more times before notification",
 
580
                         MAX_FAILED_GET_UPDATES - manager->priv->failed_get_updates_count);
 
581
                goto out;
 
582
        }
 
583
 
 
584
        /* TRANSLATORS: the updates mechanism */
 
585
        title = _("Updates");
 
586
 
 
587
        /* TRANSLATORS: we failed to get the updates multiple times,
 
588
         * and now we need to inform the user that something might be wrong */
 
589
        message = _("Unable to access software updates");
 
590
 
 
591
        /* TRANSLATORS: try again, this time launching the update viewer */
 
592
        button = _("Try again");
 
593
 
 
594
        notification = notify_notification_new (title,
 
595
                                                message,
 
596
                                                GSD_UPDATES_ICON_NORMAL);
 
597
        notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
 
598
        notify_notification_set_app_name (notification, _("Software Updates"));
 
599
        notify_notification_set_timeout (notification, 120*1000);
 
600
        notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
 
601
        notify_notification_add_action (notification, "show-update-viewer",
 
602
                                        button,
 
603
                                        libnotify_action_cb,
 
604
                                        manager, NULL);
 
605
        g_signal_connect (notification, "closed",
 
606
                          G_CALLBACK (on_notification_closed), NULL);
 
607
        ret = notify_notification_show (notification, &error);
 
608
        if (!ret) {
 
609
                g_warning ("failed to show notification: %s",
 
610
                           error->message);
 
611
                g_error_free (error);
 
612
        }
 
613
out:
 
614
        /* reset, even if the message failed */
 
615
        manager->priv->failed_get_updates_count = 0;
 
616
}
 
617
 
 
618
static void
 
619
check_updates_for_importance (GsdUpdatesManager *manager)
 
620
{
 
621
        guint i;
 
622
        PkPackage *pkg;
 
623
        GPtrArray *important_array;
 
624
 
 
625
        /* check each package */
 
626
        important_array = g_ptr_array_new ();
 
627
        for (i = 0; i < manager->priv->update_packages->len; i++) {
 
628
                pkg = g_ptr_array_index (manager->priv->update_packages, i);
 
629
                if (pk_package_get_info (pkg) == PK_INFO_ENUM_SECURITY ||
 
630
                    pk_package_get_info (pkg) == PK_INFO_ENUM_IMPORTANT)
 
631
                        g_ptr_array_add (important_array, pkg);
 
632
        }
 
633
        if (important_array->len > 0) {
 
634
                notify_critical_updates (manager,
 
635
                                         important_array);
 
636
        } else {
 
637
                notify_normal_updates_maybe (manager,
 
638
                                             manager->priv->update_packages);
 
639
        }
 
640
        g_ptr_array_unref (important_array);
 
641
}
 
642
 
 
643
static void
 
644
package_download_finished_cb (GObject *object,
 
645
                              GAsyncResult *res,
 
646
                              GsdUpdatesManager *manager)
 
647
{
 
648
        PkClient *client = PK_CLIENT(object);
 
649
        PkResults *results;
 
650
        GError *error = NULL;
 
651
        PkError *error_code = NULL;
 
652
 
 
653
        /* get the results */
 
654
        results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
 
655
        if (results == NULL) {
 
656
                if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
 
657
                        g_error_free (error);
 
658
                        return;
 
659
                }
 
660
                g_warning ("failed to download: %s",
 
661
                           error->message);
 
662
                g_error_free (error);
 
663
                notify_failed_get_updates_maybe (manager);
 
664
                return;
 
665
        }
 
666
 
 
667
        /* check error code */
 
668
        error_code = pk_results_get_error_code (results);
 
669
        if (error_code != NULL) {
 
670
                g_warning ("failed to download: %s, %s",
 
671
                           pk_error_enum_to_string (pk_error_get_code (error_code)),
 
672
                           pk_error_get_details (error_code));
 
673
                switch (pk_error_get_code (error_code)) {
 
674
                case PK_ERROR_ENUM_CANCELLED_PRIORITY:
 
675
                case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
 
676
                        g_debug ("ignoring error");
 
677
                        break;
 
678
                default:
 
679
                        notify_failed_get_updates_maybe (manager);
 
680
                        break;
 
681
                }
 
682
                goto out;
 
683
        }
 
684
 
 
685
        /* check to see if should notify */
 
686
        check_updates_for_importance (manager);
 
687
 
 
688
out:
 
689
        if (error_code != NULL)
 
690
                g_object_unref (error_code);
 
691
        if (results != NULL)
 
692
                g_object_unref (results);
 
693
}
 
694
 
 
695
static void
 
696
auto_download_updates (GsdUpdatesManager *manager)
 
697
{
 
698
        gchar **package_ids;
 
699
        guint i;
 
700
        PkPackage *pkg;
 
701
 
 
702
        /* download each package */
 
703
        package_ids = g_new0 (gchar *, manager->priv->update_packages->len + 1);
 
704
        for (i = 0; i < manager->priv->update_packages->len; i++) {
 
705
                pkg = g_ptr_array_index (manager->priv->update_packages, i);
 
706
                package_ids[i] = g_strdup (pk_package_get_id (pkg));
 
707
        }
 
708
 
 
709
#if PK_CHECK_VERSION(0,8,1)
 
710
        /* we've set only-download in PkTask */
 
711
        pk_task_update_packages_async (manager->priv->task,
 
712
                                       package_ids,
 
713
                                       manager->priv->cancellable,
 
714
                                       NULL, NULL,
 
715
                                       (GAsyncReadyCallback) package_download_finished_cb,
 
716
                                       manager);
 
717
#else
 
718
        /* download them all */
 
719
        pk_client_download_packages_async (PK_CLIENT(manager->priv->task),
 
720
                                           package_ids,
 
721
                                           NULL, /* this means system cache */
 
722
                                           manager->priv->cancellable,
 
723
                                           NULL, NULL,
 
724
                                           (GAsyncReadyCallback) package_download_finished_cb,
 
725
                                           manager);
 
726
#endif
 
727
        g_strfreev (package_ids);
 
728
}
 
729
 
 
730
static void
 
731
get_updates_finished_cb (GObject *object,
 
732
                         GAsyncResult *res,
 
733
                         GsdUpdatesManager *manager)
 
734
{
 
735
        PkClient *client = PK_CLIENT(object);
 
736
        PkResults *results;
 
737
        GError *error = NULL;
 
738
        gboolean ret;
 
739
        PkError *error_code = NULL;
 
740
 
 
741
        /* get the results */
 
742
        results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
 
743
        if (results == NULL) {
 
744
                if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
 
745
                        g_error_free (error);
 
746
                        return;
 
747
                }
 
748
                g_warning ("failed to get updates: %s",
 
749
                           error->message);
 
750
                g_error_free (error);
 
751
                notify_failed_get_updates_maybe (manager);
 
752
                goto out;
 
753
        }
 
754
 
 
755
        /* check error code */
 
756
        error_code = pk_results_get_error_code (results);
 
757
        if (error_code != NULL) {
 
758
                g_warning ("failed to get updates: %s, %s",
 
759
                           pk_error_enum_to_string (pk_error_get_code (error_code)),
 
760
                           pk_error_get_details (error_code));
 
761
                switch (pk_error_get_code (error_code)) {
 
762
                case PK_ERROR_ENUM_CANCELLED_PRIORITY:
 
763
                case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
 
764
                        g_debug ("ignoring error");
 
765
                        break;
 
766
                default:
 
767
                        notify_failed_get_updates_maybe (manager);
 
768
                        break;
 
769
                }
 
770
                goto out;
 
771
        }
 
772
 
 
773
        /* we succeeded, so clear the count */
 
774
        manager->priv->failed_get_updates_count = 0;
 
775
 
 
776
        /* so we can download or check for important & security updates */
 
777
        if (manager->priv->update_packages != NULL)
 
778
                g_ptr_array_unref (manager->priv->update_packages);
 
779
        manager->priv->update_packages = pk_results_get_package_array (results);
 
780
 
 
781
        /* we have no updates */
 
782
        if (manager->priv->update_packages->len == 0) {
 
783
                g_debug ("no updates");
 
784
                goto out;
 
785
        }
 
786
 
 
787
        /* should we auto-download the updates? */
 
788
        ret = g_settings_get_boolean (manager->priv->settings_gsd,
 
789
                                      GSD_SETTINGS_AUTO_DOWNLOAD_UPDATES);
 
790
        if (ret) {
 
791
                auto_download_updates (manager);
 
792
                goto out;
 
793
        }
 
794
 
 
795
        /* just check to see if should notify */
 
796
        check_updates_for_importance (manager);
 
797
out:
 
798
        if (error_code != NULL)
 
799
                g_object_unref (error_code);
 
800
        if (results != NULL)
 
801
                g_object_unref (results);
 
802
}
 
803
 
 
804
static void
 
805
query_updates (GsdUpdatesManager *manager)
 
806
{
 
807
        /* optimize the amount of downloaded data by setting the cache age */
 
808
        pk_client_set_cache_age (PK_CLIENT(manager->priv->task),
 
809
                                 g_settings_get_int (manager->priv->settings_gsd,
 
810
                                                     GSD_SETTINGS_FREQUENCY_GET_UPDATES));
 
811
 
 
812
        /* get new update list */
 
813
        pk_client_get_updates_async (PK_CLIENT(manager->priv->task),
 
814
                                     pk_bitfield_value (PK_FILTER_ENUM_NONE),
 
815
                                     manager->priv->cancellable,
 
816
                                     NULL, NULL,
 
817
                                     (GAsyncReadyCallback) get_updates_finished_cb,
 
818
                                     manager);
 
819
}
 
820
 
 
821
static void
 
822
due_get_updates_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager)
 
823
{
 
824
        query_updates (manager);
 
825
}
 
826
 
 
827
static gchar *
 
828
get_proxy_http (GsdUpdatesManager *manager)
 
829
{
 
830
        gboolean ret;
 
831
        gchar *host = NULL;
 
832
        gchar *password = NULL;
 
833
        gchar *proxy = NULL;
 
834
        gchar *username = NULL;
 
835
        GString *string = NULL;
 
836
        guint port;
 
837
        GDesktopProxyMode proxy_mode;
 
838
 
 
839
        proxy_mode = g_settings_get_enum (manager->priv->settings_proxy, "mode");
 
840
        if (proxy_mode != G_DESKTOP_PROXY_MODE_MANUAL)
 
841
                goto out;
 
842
 
 
843
        host = g_settings_get_string (manager->priv->settings_http,
 
844
                                      "host");
 
845
        if (host == NULL)
 
846
                goto out;
 
847
        port = g_settings_get_int (manager->priv->settings_http,
 
848
                                   "port");
 
849
 
 
850
        /* use an HTTP auth string? */
 
851
        ret = g_settings_get_boolean (manager->priv->settings_http,
 
852
                                      "use-authentication");
 
853
        if (ret) {
 
854
                username = g_settings_get_string (manager->priv->settings_http,
 
855
                                                  "authentication-user");
 
856
                password = g_settings_get_string (manager->priv->settings_http,
 
857
                                                  "authentication-password");
 
858
        }
 
859
 
 
860
        /* make PackageKit proxy string */
 
861
        string = g_string_new (host);
 
862
        if (port > 0)
 
863
                g_string_append_printf (string, ":%i", port);
 
864
        if (username != NULL && password != NULL)
 
865
                g_string_append_printf (string, "@%s:%s", username, password);
 
866
        else if (username != NULL)
 
867
                g_string_append_printf (string, "@%s", username);
 
868
        else if (password != NULL)
 
869
                g_string_append_printf (string, "@:%s", password);
 
870
        proxy = g_string_free (string, FALSE);
 
871
out:
 
872
        g_free (host);
 
873
        g_free (username);
 
874
        g_free (password);
 
875
        return proxy;
 
876
}
 
877
 
 
878
static gchar *
 
879
get_proxy_ftp (GsdUpdatesManager *manager)
 
880
{
 
881
        gchar *host = NULL;
 
882
        gchar *proxy = NULL;
 
883
        GString *string = NULL;
 
884
        guint port;
 
885
        GDesktopProxyMode proxy_mode;
 
886
 
 
887
        proxy_mode = g_settings_get_enum (manager->priv->settings_proxy, "mode");
 
888
        if (proxy_mode != G_DESKTOP_PROXY_MODE_MANUAL)
 
889
                goto out;
 
890
 
 
891
        host = g_settings_get_string (manager->priv->settings_ftp,
 
892
                                      "host");
 
893
        if (host == NULL)
 
894
                goto out;
 
895
        port = g_settings_get_int (manager->priv->settings_ftp,
 
896
                                   "port");
 
897
        if (port == 0)
 
898
                goto out;
 
899
 
 
900
        /* make PackageKit proxy string */
 
901
        string = g_string_new (host);
 
902
        if (port > 0)
 
903
                g_string_append_printf (string, ":%i", port);
 
904
        proxy = g_string_free (string, FALSE);
 
905
out:
 
906
        g_free (host);
 
907
        return proxy;
 
908
}
 
909
 
 
910
 
 
911
static void
 
912
set_proxy_cb (GObject *object, GAsyncResult *res, gpointer user_data)
 
913
{
 
914
        gboolean ret;
 
915
        GError *error = NULL;
 
916
        PkControl *control = PK_CONTROL (object);
 
917
 
 
918
        /* get the result */
 
919
        ret = pk_control_set_proxy_finish (control, res, &error);
 
920
        if (!ret) {
 
921
                if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 
922
                        g_warning ("failed to set proxies: %s", error->message);
 
923
                g_error_free (error);
 
924
        }
 
925
}
 
926
 
 
927
static void
 
928
reload_proxy_settings (GsdUpdatesManager *manager)
 
929
{
 
930
        gchar *proxy_http;
 
931
        gchar *proxy_ftp;
 
932
 
 
933
        proxy_http = get_proxy_http (manager);
 
934
        proxy_ftp = get_proxy_ftp (manager);
 
935
 
 
936
        /* send to daemon */
 
937
        pk_control_set_proxy_async (manager->priv->control,
 
938
                                    proxy_http,
 
939
                                    proxy_ftp,
 
940
                                    NULL,
 
941
                                    set_proxy_cb,
 
942
                                    manager);
 
943
 
 
944
        g_free (proxy_http);
 
945
        g_free (proxy_ftp);
 
946
}
 
947
 
 
948
static void
 
949
settings_changed_cb (GSettings         *settings,
 
950
                     const char        *key,
 
951
                     GsdUpdatesManager *manager)
 
952
{
 
953
        reload_proxy_settings (manager);
 
954
}
 
955
 
 
956
static void
 
957
settings_gsd_changed_cb (GSettings         *settings,
 
958
                         const char        *key,
 
959
                         GsdUpdatesManager *manager)
 
960
{
 
961
}
 
962
 
 
963
static void
 
964
session_inhibit (GsdUpdatesManager *manager)
 
965
{
 
966
        const gchar *reason;
 
967
        GError *error = NULL;
 
968
        GVariant *retval = NULL;
 
969
 
 
970
        /* state invalid somehow */
 
971
        if (manager->priv->inhibit_cookie != 0) {
 
972
                g_warning ("already locked");
 
973
                goto out;
 
974
        }
 
975
 
 
976
        /* TRANSLATORS: the reason why we've inhibited it */
 
977
        reason = _("A transaction that cannot be interrupted is running");
 
978
        retval = g_dbus_proxy_call_sync (manager->priv->proxy_session,
 
979
                                         "Inhibit",
 
980
                                         g_variant_new ("(susu)",
 
981
                                                        "gnome-settings-daemon", /* app-id */
 
982
                                                        0, /* xid */
 
983
                                                        reason, /* reason */
 
984
                                                        4 /* flags */),
 
985
                                         G_DBUS_CALL_FLAGS_NONE,
 
986
                                         -1,
 
987
                                         manager->priv->cancellable,
 
988
                                         &error);
 
989
        if (retval == NULL) {
 
990
                g_warning ("failed to inhibit gnome-session: %s",
 
991
                           error->message);
 
992
                g_error_free (error);
 
993
                goto out;
 
994
        }
 
995
 
 
996
        /* get cookie */
 
997
        g_variant_get (retval, "(u)",
 
998
                       &manager->priv->inhibit_cookie);
 
999
out:
 
1000
        if (retval != NULL)
 
1001
                g_variant_unref (retval);
 
1002
}
 
1003
 
 
1004
static void
 
1005
session_uninhibit (GsdUpdatesManager *manager)
 
1006
{
 
1007
        GError *error = NULL;
 
1008
        GVariant *retval = NULL;
 
1009
 
 
1010
        /* state invalid somehow */
 
1011
        if (manager->priv->inhibit_cookie == 0) {
 
1012
                g_warning ("not locked");
 
1013
                goto out;
 
1014
        }
 
1015
        retval = g_dbus_proxy_call_sync (manager->priv->proxy_session,
 
1016
                                         "Uninhibit",
 
1017
                                         g_variant_new ("(u)",
 
1018
                                                        manager->priv->inhibit_cookie),
 
1019
                                         G_DBUS_CALL_FLAGS_NONE,
 
1020
                                         -1,
 
1021
                                         manager->priv->cancellable,
 
1022
                                         &error);
 
1023
        if (retval == NULL) {
 
1024
                g_warning ("failed to uninhibit gnome-session: %s",
 
1025
                           error->message);
 
1026
                g_error_free (error);
 
1027
                goto out;
 
1028
        }
 
1029
out:
 
1030
        manager->priv->inhibit_cookie = 0;
 
1031
        if (retval != NULL)
 
1032
                g_variant_unref (retval);
 
1033
}
 
1034
 
 
1035
static void
 
1036
notify_locked_cb (PkControl *control,
 
1037
                  GParamSpec *pspec,
 
1038
                  GsdUpdatesManager *manager)
 
1039
{
 
1040
        gboolean locked;
 
1041
 
 
1042
        g_object_get (control, "locked", &locked, NULL);
 
1043
 
 
1044
        /* TODO: locked is a bit harsh, we can probably still allow
 
1045
         * reboot when packages are downloading or the transaction is
 
1046
         * depsolving */
 
1047
        if (locked) {
 
1048
                session_inhibit (manager);
 
1049
        } else {
 
1050
                session_uninhibit (manager);
 
1051
        }
 
1052
}
 
1053
 
 
1054
static void
 
1055
update_viewer_appeared_cb (GDBusConnection *connection,
 
1056
                           const gchar *name,
 
1057
                           const gchar *name_owner,
 
1058
                           gpointer user_data)
 
1059
{
 
1060
        GsdUpdatesManager *manager = GSD_UPDATES_MANAGER (user_data);
 
1061
 
 
1062
        /* close any existing notification */
 
1063
        if (manager->priv->notification_updates != NULL) {
 
1064
                g_debug ("update viewer on the bus, clearing bubble");
 
1065
                notify_notification_close (manager->priv->notification_updates, NULL);
 
1066
                manager->priv->notification_updates = NULL;
 
1067
        }
 
1068
}
 
1069
 
 
1070
static gboolean
 
1071
file_exists_in_root (const gchar *root, const gchar *filename)
 
1072
{
 
1073
        gboolean ret = FALSE;
 
1074
        GFile *source;
 
1075
        gchar *source_path;
 
1076
 
 
1077
        source_path = g_build_filename (root, filename, NULL);
 
1078
        source = g_file_new_for_path (source_path);
 
1079
 
 
1080
        /* ignore virtual mountpoints */
 
1081
        if (!g_file_is_native (source))
 
1082
                goto out;
 
1083
 
 
1084
        /* an interesting file exists */
 
1085
        ret = g_file_query_exists (source, NULL);
 
1086
        g_debug ("checking for %s: %s", source_path, ret ? "yes" : "no");
 
1087
        if (!ret)
 
1088
                goto out;
 
1089
out:
 
1090
        g_free (source_path);
 
1091
        g_object_unref (source);
 
1092
        return ret;
 
1093
}
 
1094
 
 
1095
static void
 
1096
mount_added_cb (GVolumeMonitor *volume_monitor,
 
1097
                GMount *mount,
 
1098
                GsdUpdatesManager *manager)
 
1099
{
 
1100
        gboolean ret = FALSE;
 
1101
        gchar **filenames = NULL;
 
1102
        gchar *media_repo_filenames;
 
1103
        gchar *root_path;
 
1104
        GFile *root;
 
1105
        guint i;
 
1106
 
 
1107
        /* check if any installed media is an install disk */
 
1108
        root = g_mount_get_root (mount);
 
1109
        root_path = g_file_get_path (root);
 
1110
 
 
1111
        /* use settings */
 
1112
        media_repo_filenames = g_settings_get_string (manager->priv->settings_gsd,
 
1113
                                                      GSD_SETTINGS_MEDIA_REPO_FILENAMES);
 
1114
        if (media_repo_filenames == NULL) {
 
1115
                g_warning ("failed to get media repo filenames");
 
1116
                goto out;
 
1117
        }
 
1118
 
 
1119
        /* search each possible filename */
 
1120
        filenames = g_strsplit (media_repo_filenames, ",", -1);
 
1121
        for (i=0; filenames[i] != NULL; i++) {
 
1122
                ret = file_exists_in_root (root_path, filenames[i]);
 
1123
                if (ret)
 
1124
                        break;
 
1125
        }
 
1126
 
 
1127
        /* do an updates check with the new media */
 
1128
        if (ret)
 
1129
                query_updates (manager);
 
1130
out:
 
1131
        g_strfreev (filenames);
 
1132
        g_free (media_repo_filenames);
 
1133
        g_free (root_path);
 
1134
        g_object_unref (root);
 
1135
}
 
1136
 
 
1137
#define PK_OFFLINE_UPDATE_RESULTS_GROUP         "PackageKit Offline Update Results"
 
1138
#define PK_OFFLINE_UPDATE_RESULTS_FILENAME      "/var/lib/PackageKit/offline-update-competed"
 
1139
 
 
1140
static gboolean
 
1141
check_offline_update_cb (gpointer user_data)
 
1142
{
 
1143
        const gchar *message;
 
1144
        const gchar *title;
 
1145
        gboolean ret;
 
1146
        gboolean success;
 
1147
        gchar *error_code = NULL;
 
1148
        gchar *error_details = NULL;
 
1149
        gchar *packages = NULL;
 
1150
        GError *error = NULL;
 
1151
        GKeyFile *key_file = NULL;
 
1152
        GsdUpdatesManager *manager = (GsdUpdatesManager *) user_data;
 
1153
        guint i;
 
1154
        guint num_packages = 1;
 
1155
        NotifyNotification *notification;
 
1156
        PkErrorEnum error_enum = PK_ERROR_ENUM_UNKNOWN;
 
1157
 
 
1158
        /* was any offline update attempted */
 
1159
        if (!g_file_test (PK_OFFLINE_UPDATE_RESULTS_FILENAME, G_FILE_TEST_EXISTS))
 
1160
                goto out;
 
1161
 
 
1162
        /* open the file and see what happened */
 
1163
        key_file = g_key_file_new ();
 
1164
        ret = g_key_file_load_from_file (key_file,
 
1165
                                         PK_OFFLINE_UPDATE_RESULTS_FILENAME,
 
1166
                                         G_KEY_FILE_NONE,
 
1167
                                         &error);
 
1168
        if (!ret) {
 
1169
                g_warning ("failed to open %s: %s",
 
1170
                           PK_OFFLINE_UPDATE_RESULTS_FILENAME,
 
1171
                           error->message);
 
1172
                g_error_free (error);
 
1173
                goto out;
 
1174
        }
 
1175
        success = g_key_file_get_boolean (key_file,
 
1176
                                          PK_OFFLINE_UPDATE_RESULTS_GROUP,
 
1177
                                          "Success",
 
1178
                                          NULL);
 
1179
        if (success) {
 
1180
                packages = g_key_file_get_string (key_file,
 
1181
                                                  PK_OFFLINE_UPDATE_RESULTS_GROUP,
 
1182
                                                  "Packages",
 
1183
                                                  NULL);
 
1184
                if (packages == NULL) {
 
1185
                        g_warning ("No 'Packages' in %s",
 
1186
                                   PK_OFFLINE_UPDATE_RESULTS_FILENAME);
 
1187
                        goto out;
 
1188
                }
 
1189
 
 
1190
                /* count the packages for translators */
 
1191
                for (i = 0; packages[i] != '\0'; i++) {
 
1192
                        if (packages[i] == ',')
 
1193
                                num_packages++;
 
1194
                }
 
1195
 
 
1196
                /* TRANSLATORS: title in the libnotify popup */
 
1197
                title = ngettext ("Software Update Installed",
 
1198
                                  "Software Updates Installed",
 
1199
                                  num_packages);
 
1200
 
 
1201
                /* TRANSLATORS: message when we've done offline updates */
 
1202
                message = ngettext ("An important OS update has been installed.",
 
1203
                                    "Important OS updates have been installed.",
 
1204
                                    num_packages);
 
1205
 
 
1206
                /* no need to keep the file around anymore */
 
1207
                clear_offline_updates_message ();
 
1208
        } else {
 
1209
                /* get error details */
 
1210
                manager->priv->offline_update_error = pk_error_new ();
 
1211
 
 
1212
                error_code = g_key_file_get_string (key_file,
 
1213
                                                    PK_OFFLINE_UPDATE_RESULTS_GROUP,
 
1214
                                                    "ErrorCode",
 
1215
                                                    NULL);
 
1216
                if (error_code != NULL)
 
1217
                        error_enum = pk_error_enum_from_string (error_code);
 
1218
                error_details = g_key_file_get_string (key_file,
 
1219
                                                       PK_OFFLINE_UPDATE_RESULTS_GROUP,
 
1220
                                                       "ErrorDetails",
 
1221
                                                       NULL);
 
1222
                g_object_set (manager->priv->offline_update_error,
 
1223
                              "code", error_enum,
 
1224
                              "details", error_details,
 
1225
                              NULL);
 
1226
 
 
1227
                /* TRANSLATORS: title in the libnotify popup */
 
1228
                title = _("Software Updates Failed");
 
1229
 
 
1230
                /* TRANSLATORS: message when we've not done offline updates */
 
1231
                message = _("An important OS update failed to be installed.");
 
1232
        }
 
1233
 
 
1234
        /* do the bubble */
 
1235
        g_debug ("title=%s, message=%s", title, message);
 
1236
        notification = notify_notification_new (title,
 
1237
                                                message,
 
1238
                                                GSD_UPDATES_ICON_URGENT);
 
1239
        notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
 
1240
        notify_notification_set_app_name (notification, _("Software Updates"));
 
1241
        notify_notification_set_timeout (notification, -1);
 
1242
        notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
 
1243
        if (success) {
 
1244
#if 0
 
1245
                notify_notification_add_action (notification, "review-offline-updates",
 
1246
                                                /* TRANSLATORS: button: review the offline update changes */
 
1247
                                                _("Review"), libnotify_action_cb, manager, NULL);
 
1248
#endif
 
1249
        } else {
 
1250
                notify_notification_add_action (notification, "error-offline-updates",
 
1251
                                                /* TRANSLATORS: button: review the offline update changes */
 
1252
                                                _("Show details"), libnotify_action_cb, manager, NULL);
 
1253
        }
 
1254
        notify_notification_add_action (notification, "clear-offline-updates",
 
1255
                                        /* TRANSLATORS: button: clear notification */
 
1256
                                        _("OK"), libnotify_action_cb, manager, NULL);
 
1257
        g_signal_connect (notification, "closed",
 
1258
                          G_CALLBACK (on_notification_closed), NULL);
 
1259
        ret = notify_notification_show (notification, &error);
 
1260
        if (!ret) {
 
1261
                g_warning ("error: %s", error->message);
 
1262
                g_error_free (error);
 
1263
        }
 
1264
out:
 
1265
        g_free (packages);
 
1266
        g_free (error_code);
 
1267
        g_free (error_details);
 
1268
        if (key_file != NULL)
 
1269
                g_key_file_free (key_file);
 
1270
        manager->priv->offline_update_id = 0;
 
1271
        return FALSE;
 
1272
}
 
1273
 
 
1274
gboolean
 
1275
gsd_updates_manager_start (GsdUpdatesManager *manager,
 
1276
                           GError **error)
 
1277
{
 
1278
        gboolean ret = FALSE;
 
1279
 
 
1280
        g_debug ("Starting updates manager");
 
1281
 
 
1282
        /* use PackageKit */
 
1283
        manager->priv->cancellable = g_cancellable_new ();
 
1284
        manager->priv->control = pk_control_new ();
 
1285
        g_signal_connect (manager->priv->control, "notify::locked",
 
1286
                          G_CALLBACK (notify_locked_cb), manager);
 
1287
        manager->priv->task = pk_task_new ();
 
1288
        g_object_set (manager->priv->task,
 
1289
                      "background", TRUE,
 
1290
                      "interactive", FALSE,
 
1291
#if PK_CHECK_VERSION(0,8,1)
 
1292
                      "only-download", TRUE,
 
1293
#endif
 
1294
                      NULL);
 
1295
 
 
1296
        /* watch UDev for missing firmware */
 
1297
        manager->priv->firmware = gsd_updates_firmware_new ();
 
1298
 
 
1299
        /* get automatic callbacks about when we should check for
 
1300
         * updates, refresh-caches and upgrades */
 
1301
        manager->priv->refresh = gsd_updates_refresh_new ();
 
1302
        g_signal_connect (manager->priv->refresh, "get-upgrades",
 
1303
                          G_CALLBACK (due_get_upgrades_cb), manager);
 
1304
        g_signal_connect (manager->priv->refresh, "refresh-cache",
 
1305
                          G_CALLBACK (due_refresh_cache_cb), manager);
 
1306
        g_signal_connect (manager->priv->refresh, "get-updates",
 
1307
                          G_CALLBACK (due_get_updates_cb), manager);
 
1308
 
 
1309
        /* get proxy settings */
 
1310
        manager->priv->settings_proxy = g_settings_new ("org.gnome.system.proxy");
 
1311
        g_signal_connect (manager->priv->settings_proxy, "changed",
 
1312
                          G_CALLBACK (settings_changed_cb), manager);
 
1313
 
 
1314
        /* get http settings */
 
1315
        manager->priv->settings_http = g_settings_new ("org.gnome.system.proxy.http");
 
1316
        g_signal_connect (manager->priv->settings_http, "changed",
 
1317
                          G_CALLBACK (settings_changed_cb), manager);
 
1318
 
 
1319
        /* get ftp settings */
 
1320
        manager->priv->settings_ftp = g_settings_new ("org.gnome.system.proxy.ftp");
 
1321
        g_signal_connect (manager->priv->settings_ftp, "changed",
 
1322
                          G_CALLBACK (settings_changed_cb), manager);
 
1323
 
 
1324
        /* get ftp settings */
 
1325
        manager->priv->settings_gsd = g_settings_new ("org.gnome.settings-daemon.plugins.updates");
 
1326
        g_signal_connect (manager->priv->settings_gsd, "changed",
 
1327
                          G_CALLBACK (settings_gsd_changed_cb), manager);
 
1328
 
 
1329
        /* use gnome-session for the idle detection */
 
1330
        manager->priv->proxy_session =
 
1331
                gnome_settings_session_get_session_proxy ();
 
1332
        if (manager->priv->proxy_session == NULL)
 
1333
                goto out;
 
1334
 
 
1335
        /* if the update viewer is started, then hide the notification */
 
1336
        manager->priv->update_viewer_watcher_id =
 
1337
                g_bus_watch_name (G_BUS_TYPE_SESSION,
 
1338
                                  "org.freedesktop.PackageKit.UpdateViewer",
 
1339
                                  G_BUS_NAME_WATCHER_FLAGS_NONE,
 
1340
                                  update_viewer_appeared_cb,
 
1341
                                  NULL,
 
1342
                                  manager,
 
1343
                                  NULL);
 
1344
 
 
1345
        /* get a volume monitor so we can watch media */
 
1346
        manager->priv->volume_monitor = g_volume_monitor_get ();
 
1347
        g_signal_connect (manager->priv->volume_monitor, "mount-added",
 
1348
                          G_CALLBACK (mount_added_cb), manager);
 
1349
 
 
1350
        /* coldplug */
 
1351
        reload_proxy_settings (manager);
 
1352
 
 
1353
        /* check for offline update */
 
1354
        manager->priv->offline_update_id =
 
1355
                g_timeout_add_seconds (GSD_UPDATES_CHECK_OFFLINE_TIMEOUT,
 
1356
                                       check_offline_update_cb,
 
1357
                                       manager);
 
1358
 
 
1359
        /* success */
 
1360
        ret = TRUE;
 
1361
        g_debug ("Started updates manager");
 
1362
out:
 
1363
        return ret;
 
1364
}
 
1365
 
 
1366
void
 
1367
gsd_updates_manager_stop (GsdUpdatesManager *manager)
 
1368
{
 
1369
        g_debug ("Stopping updates manager");
 
1370
 
 
1371
        g_clear_object (&manager->priv->settings_proxy);
 
1372
        g_clear_object (&manager->priv->settings_http);
 
1373
        g_clear_object (&manager->priv->settings_ftp);
 
1374
        g_clear_object (&manager->priv->settings_gsd);
 
1375
        g_clear_object (&manager->priv->control);
 
1376
        g_clear_object (&manager->priv->task);
 
1377
        g_clear_object (&manager->priv->refresh);
 
1378
        g_clear_object (&manager->priv->firmware);
 
1379
        g_clear_object (&manager->priv->proxy_session);
 
1380
        g_clear_object (&manager->priv->volume_monitor);
 
1381
        if (manager->priv->cancellable) {
 
1382
                g_cancellable_cancel (manager->priv->cancellable);
 
1383
                g_clear_object (&manager->priv->cancellable);
 
1384
        }
 
1385
        if (manager->priv->update_viewer_watcher_id != 0) {
 
1386
                g_bus_unwatch_name (manager->priv->update_viewer_watcher_id);
 
1387
                manager->priv->update_viewer_watcher_id = 0;
 
1388
        }
 
1389
        if (manager->priv->offline_update_id) {
 
1390
                g_source_remove (manager->priv->offline_update_id);
 
1391
                manager->priv->offline_update_id = 0;
 
1392
        }
 
1393
        if (manager->priv->update_packages != NULL) {
 
1394
                g_ptr_array_unref (manager->priv->update_packages);
 
1395
                manager->priv->update_packages = NULL;
 
1396
        }
 
1397
        g_clear_object (&manager->priv->offline_update_error);
 
1398
}
 
1399
 
 
1400
static GObject *
 
1401
gsd_updates_manager_constructor (
 
1402
                GType type,
 
1403
                guint n_construct_properties,
 
1404
                GObjectConstructParam *construct_properties)
 
1405
{
 
1406
        GsdUpdatesManager *m;
 
1407
 
 
1408
        m = GSD_UPDATES_MANAGER (G_OBJECT_CLASS (gsd_updates_manager_parent_class)->constructor (
 
1409
                                                           type,
 
1410
                                                           n_construct_properties,
 
1411
                                                           construct_properties));
 
1412
 
 
1413
        return G_OBJECT (m);
 
1414
}
 
1415
 
 
1416
static void
 
1417
gsd_updates_manager_dispose (GObject *object)
 
1418
{
 
1419
        GsdUpdatesManager *manager;
 
1420
 
 
1421
        manager = GSD_UPDATES_MANAGER (object);
 
1422
 
 
1423
        gsd_updates_manager_stop (manager);
 
1424
 
 
1425
        G_OBJECT_CLASS (gsd_updates_manager_parent_class)->dispose (object);
 
1426
}
 
1427
 
 
1428
static void
 
1429
gsd_updates_manager_class_init (GsdUpdatesManagerClass *klass)
 
1430
{
 
1431
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
1432
 
 
1433
        object_class->constructor = gsd_updates_manager_constructor;
 
1434
        object_class->dispose = gsd_updates_manager_dispose;
 
1435
 
 
1436
        g_type_class_add_private (klass, sizeof (GsdUpdatesManagerPrivate));
 
1437
}
 
1438
 
 
1439
static void
 
1440
gsd_updates_manager_init (GsdUpdatesManager *manager)
 
1441
{
 
1442
        manager->priv = GSD_UPDATES_MANAGER_GET_PRIVATE (manager);
 
1443
}
 
1444
 
 
1445
GsdUpdatesManager *
 
1446
gsd_updates_manager_new (void)
 
1447
{
 
1448
        if (manager_object) {
 
1449
                g_object_ref (manager_object);
 
1450
        } else {
 
1451
                manager_object = g_object_new (GSD_TYPE_UPDATES_MANAGER, NULL);
 
1452
                g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object);
 
1453
        }
 
1454
 
 
1455
        return GSD_UPDATES_MANAGER (manager_object);
 
1456
}