~ubuntu-core-dev/update-notifier/ubuntu

« back to all changes in this revision

Viewing changes to src/update.c

  • Committer: Julian Andres Klode
  • Date: 2019-04-02 13:18:28 UTC
  • mfrom: (957.1.5 esm)
  • Revision ID: juliank@ubuntu.com-20190402131828-n7brmzl4gwgvshoe
* Rewrite and extend motd messaging (LP: #1822340)
* Count ESM security updates as security updates

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 
9
9
#include <glib.h>
10
10
#include <glib/gstdio.h>
 
11
#include <gio/gio.h>
11
12
 
12
13
#include <sys/types.h>
13
14
#include <sys/stat.h>
14
15
#include <unistd.h>
15
16
#include <stdlib.h>
16
 
#include <dbus/dbus-glib.h>
17
17
 
18
18
#include "update-notifier.h"
19
19
#include "update.h"
 
20
#include "trayappletui.h"
20
21
 
21
22
#define UPGRADE_CHECKER PACKAGE_LIB_DIR"/update-notifier/apt-check"
 
23
#define PACKAGE_SYSTEM_LOCKED PACKAGE_LIB_DIR"/update-notifier/package-system-locked"
22
24
 
23
 
// command, description, desktopfile, needs_gksu
 
25
// command, description, desktopfile, needs_pkexec
24
26
const char* actions[][4] = {
25
 
   { "/usr/bin/update-manager", N_("Show updates"), 
 
27
   { "/usr/lib/update-notifier/backend_helper.py show_updates",
 
28
     N_("Show updates"), 
26
29
     "/usr/share/applications/update-manager.desktop", 
27
30
     GINT_TO_POINTER(FALSE) },
28
 
 
29
 
   { "/usr/sbin/synaptic --dist-upgrade-mode --non-interactive --hide-main-window -o Synaptic::AskRelated=true",
 
31
   { "/usr/lib/update-notifier/backend_helper.py install_all_updates",
30
32
     N_("Install all updates"), "/usr/share/applications/synaptic.desktop", 
31
 
     GINT_TO_POINTER(TRUE)
 
33
     GINT_TO_POINTER(FALSE)
32
34
   },
33
 
   { "/usr/sbin/synaptic --update-at-startup --non-interactive --hide-main-window", 
 
35
   { "/usr/lib/update-notifier/backend_helper.py check_updates",
34
36
     N_("Check for updates"), "/usr/share/applications/synaptic.desktop", 
35
 
     GINT_TO_POINTER(TRUE) },
36
 
   { "/usr/sbin/synaptic", N_("Start package manager"), 
37
 
     "/usr/share/applications/synaptic.desktop", 
38
 
     GINT_TO_POINTER(TRUE)},
 
37
     GINT_TO_POINTER(FALSE) },
 
38
   { "/usr/lib/update-notifier/backend_helper.py start_packagemanager",
 
39
     N_("Start package manager"), "/usr/share/applications/synaptic.desktop",
 
40
     GINT_TO_POINTER(FALSE)},
39
41
   { NULL, NULL, NULL }
40
42
};
41
43
 
54
56
   va_end(va);
55
57
}
56
58
 
 
59
#ifndef HAVE_APP_INDICATOR
57
60
static gboolean
58
 
activate_cb (GtkWidget *widget, 
 
61
gtk_status_icon_click_activate_cb (GtkWidget *widget, 
59
62
             TrayApplet *ta)
60
63
{
61
64
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
69
72
   last_action = time(NULL);
70
73
   return TRUE;
71
74
}
72
 
 
73
 
static gboolean
74
 
popup_cb (GtkStatusIcon *status_icon,
75
 
          guint          button,
76
 
          guint          activate_time,
77
 
          TrayApplet     *un)
78
 
{
79
 
   gtk_menu_set_screen (GTK_MENU (un->menu),
80
 
                        gtk_status_icon_get_screen(un->tray_icon));
81
 
   gtk_menu_popup (GTK_MENU (un->menu), NULL, NULL, 
82
 
                   gtk_status_icon_position_menu, un->tray_icon,
83
 
                   button, activate_time);
84
 
   return TRUE;
85
 
}
86
 
 
87
 
void
 
75
#endif
 
76
 
 
77
static void
88
78
update_trayicon_update_tooltip (TrayApplet *ta, int num_upgrades)
89
79
{
90
80
   //g_print("update_tooltip: %p %p %p\n", ta, ta->tooltip, ta->eventbox);
94
84
                                      "There are %i updates available",
95
85
                                      num_upgrades),
96
86
                             num_upgrades);
97
 
   gtk_status_icon_set_tooltip(ta->tray_icon, updates);
 
87
   tray_applet_ui_set_tooltip_text(ta, updates);
98
88
   g_free(updates);
99
89
}
100
90
 
101
91
 
102
 
void 
103
 
cb_action(GObject *self, void *user_data)
 
92
static void 
 
93
cb_action(GObject *self, void *user_data __attribute__ ((__unused__)))
104
94
{
105
 
   TrayApplet *ta = user_data;
106
 
        
107
95
   int i = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(self), "action"));
108
96
   invoke (actions[i][0], _(actions[i][2]), (long)actions[i][3]);
109
 
 
110
 
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
111
 
   gconf_client_set_int(priv->gconf, GCONF_KEY_DEFAULT_ACTION, i, NULL);
112
97
}
113
98
 
114
 
void 
 
99
static void 
115
100
cb_preferences(GObject *self, void *user_data)
116
101
{
117
 
   invoke_with_gksu("/usr/bin/software-properties-gtk",
118
 
                    "/usr/share/applications/software-properties.desktop",
119
 
                    FALSE);    
 
102
   invoke("/usr/bin/software-properties-gtk",
 
103
          "/usr/share/applications/software-properties.desktop",
 
104
          FALSE);    
120
105
}
121
106
 
122
 
void 
 
107
static void 
123
108
cb_toggled_show_notifications(GObject *self, void *data)
124
109
{
125
110
      TrayApplet *ta = (TrayApplet*)data;
126
111
      UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
127
112
 
128
113
      gboolean b = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(self));
129
 
      gconf_client_set_bool(priv->gconf, GCONF_KEY_NO_UPDATE_NOTIFICATIONS, 
130
 
                            !b,NULL);
 
114
      g_settings_set_boolean(ta->un->settings,
 
115
                             SETTINGS_KEY_NO_UPDATE_NOTIFICATIONS, !b);
131
116
      
132
117
 
133
 
      NotifyNotification *n = priv->active_notification;
134
 
      if(n != NULL) {
135
 
         notify_notification_close(n, NULL);
136
 
         priv->active_notification = NULL;
 
118
      if(priv->active_notification != NULL) {
 
119
         notify_notification_close(priv->active_notification, NULL);
 
120
         g_clear_object(&priv->active_notification);
137
121
      }
138
122
}
139
123
 
140
124
 
141
 
void
 
125
static void
142
126
update_trayicon_create_menu(TrayApplet *ta)
143
127
{
144
128
        GtkWidget *menuitem;
161
145
        gtk_menu_shell_append (GTK_MENU_SHELL (ta->menu), menuitem);
162
146
 
163
147
        menuitem = gtk_check_menu_item_new_with_label(_("Show notifications"));
164
 
        UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
165
 
        gboolean b = gconf_client_get_bool(priv->gconf,
166
 
                                           GCONF_KEY_NO_UPDATE_NOTIFICATIONS, 
167
 
                                           NULL);
 
148
        gboolean b = g_settings_get_boolean(ta->un->settings,
 
149
                                            SETTINGS_KEY_NO_UPDATE_NOTIFICATIONS);
168
150
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), !b);
169
151
        gtk_menu_shell_append (GTK_MENU_SHELL (ta->menu), menuitem);
170
152
        g_signal_connect(G_OBJECT(menuitem), "toggled", 
184
166
void 
185
167
update_apt_is_running(TrayApplet *ta, gboolean is_running)
186
168
{
187
 
   g_debug_update("update_apt_is_running: %i\n",is_running);
 
169
   g_debug_update("update_apt_is_running: %i",is_running);
188
170
   if(ta == NULL)
189
171
      return;
190
172
 
192
174
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
193
175
   priv->apt_is_running = is_running;
194
176
 
195
 
   // if the user wants auto-launch mode, do not show the icon
196
 
   // the auto launch stuff will do its magic later
197
 
   if(gconf_client_get_bool(priv->gconf, GCONF_KEY_AUTO_LAUNCH, NULL))
198
 
      return;
 
177
   // everybody wants auto-launch mode
 
178
   return;
199
179
 
200
180
   if(is_running) {
201
 
 
 
181
#ifdef HAVE_APP_INDICATOR
 
182
      // we can't do fancy stuff like the gray-out with app-indicator,
 
183
      // so we just hide the tray thing here
 
184
      tray_applet_ui_set_visible(ta, FALSE);
 
185
#else
202
186
      // gray out the icon if apt is running, we do this only once,
203
187
      // after the first time, the storage_type changes from ICON_NAME to
204
188
      // IMAGE_PIXBUF
216
200
      }
217
201
 
218
202
      // and update the tooltip
219
 
      gtk_status_icon_set_tooltip(ta->tray_icon, _("A package manager is working"));
 
203
      tray_applet_ui_set_tooltip_text(ta->tray_icon, _("A package manager is working"));
220
204
      // and show it
221
 
      gtk_status_icon_set_visible(ta->tray_icon, TRUE);
 
205
      tray_applet_ui_set_visible(ta->tray_icon, TRUE);
 
206
#endif
222
207
 
223
208
      if(priv->active_notification != NULL) {
224
209
         notify_notification_close(priv->active_notification, NULL);
225
 
         priv->active_notification = NULL;
 
210
         g_clear_object(&priv->active_notification);
226
211
      }
227
212
   } else {
228
 
      gtk_status_icon_set_from_icon_name(ta->tray_icon, ta->name);
 
213
      tray_applet_ui_set_icon(ta, ta->name);
229
214
   }
230
215
}
231
216
 
236
221
   TrayApplet *ta = (TrayApplet *)user_data;
237
222
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
238
223
 
239
 
   // apt is runing, no point in showing a notification
 
224
   // apt is running, no point in showing a notification
240
225
   if(priv->apt_is_running) 
241
226
      return TRUE;
242
227
 
243
228
   // check if the update-icon is still visible (in the delay time a 
244
229
   // update may already have been performed)
245
 
   if(!gtk_status_icon_get_visible(ta->tray_icon))
 
230
   if(!tray_applet_ui_get_visible(ta))
246
231
      return FALSE;
247
232
 
248
 
   GdkRectangle area;
249
 
   gtk_status_icon_get_geometry(ta->tray_icon, NULL, &area, NULL);
250
 
 
251
 
   // no usefull coordiante yet, do another timeout
252
 
   if(area.x <= 0 || area.y <= 0 || area.width <= 0 || area.height <= 0)
253
 
      return TRUE;
254
 
 
255
233
   // now show a notification handle 
256
234
   gchar *updates;
257
235
   updates = g_strdup_printf(ngettext("There is %i update available. "
264
242
                                      "available updates.",
265
243
                                      priv->num_upgrades), 
266
244
                             priv->num_upgrades);
267
 
   NotifyNotification *n = notify_notification_new_with_status_icon(
 
245
   NotifyNotification *n = notify_notification_new(
268
246
                              _("Software updates available"),
269
247
                              updates,
270
 
                              NULL, 
271
 
                              ta->tray_icon);
 
248
                              NULL);
272
249
 
273
250
   GdkPixbuf* pix= gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), 
274
251
                                            GTK_STOCK_DIALOG_INFO, 48,0,NULL);
277
254
   notify_notification_set_timeout (n, 60*1000);
278
255
   notify_notification_show(n, NULL);
279
256
   // save the notification handle
 
257
   if (priv->active_notification)
 
258
      g_object_unref(priv->active_notification);
280
259
   priv->active_notification = n;
281
260
 
282
261
   // remove this from the timeout now
284
263
   return FALSE;
285
264
}
286
265
 
287
 
void 
 
266
static void 
288
267
show_error(TrayApplet *ta, gchar *error_str)
289
268
{
290
 
   gtk_status_icon_set_tooltip(ta->tray_icon, error_str);
291
 
   gtk_status_icon_set_from_icon_name(ta->tray_icon, "dialog-error");
292
 
   gtk_status_icon_set_visible(ta->tray_icon, TRUE);
 
269
   tray_applet_ui_set_tooltip_text(ta, error_str);
 
270
   tray_applet_ui_set_icon(ta, "dialog-error");
 
271
   tray_applet_ui_set_visible(ta, TRUE);
293
272
}
294
273
 
295
274
static gboolean
298
277
   struct stat buf;
299
278
   if ((stat("/var/lib/apt/periodic/update-success-stamp", &buf) == 0) &&
300
279
       (time(NULL) - buf.st_mtime > OUTDATED_NAG_AGE) ) {
301
 
      gtk_status_icon_set_visible (ta->tray_icon, TRUE);
 
280
      tray_applet_ui_set_visible (ta, TRUE);
302
281
      ta->name = "gtk-dialog-warning-panel";
303
 
      GdkPixbuf *src = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
304
 
                                                ta->name, 48, 
305
 
                                                GTK_ICON_LOOKUP_GENERIC_FALLBACK, 
306
 
                                                NULL);
307
 
      gtk_status_icon_set_from_pixbuf(ta->tray_icon, src);
308
 
      g_object_unref(src);
309
 
      gtk_status_icon_set_tooltip(ta->tray_icon,
 
282
      tray_applet_ui_set_icon(ta, ta->name);
 
283
      tray_applet_ui_set_tooltip_text(ta,
310
284
                                  _("The update information is outdated. "
311
285
                                    "This may be caused by network "
312
286
                                    "problems or by a repository that "
313
287
                                    "is no longer available. "
314
288
                                    "Please update manually "
315
 
                                    "by clicking on this icon and then "
316
 
                                    "selecting 'Check for updates' and "
317
 
                                    "check if some of the listed "
318
 
                                    "repositories fail."
 
289
                                    "by selecting 'Show updates' from "
 
290
                                    "the indicator menu, and watching "
 
291
                                    "for any failing repositories."
319
292
                                 ));
320
293
   }
321
294
   return FALSE;
322
295
}
323
296
 
324
 
// use ubuntu-system-service (if available) to check
 
297
// use package-system-locked to check
325
298
// if the dpkg lock is taken currently or not
326
299
//
327
300
// if uncertain, return FALSE 
328
301
static gboolean
329
 
dpkg_lock_is_taken ()
 
302
dpkg_lock_is_taken (void)
330
303
{
331
 
   DBusGConnection *connection;
332
 
   GError *error;
333
 
   DBusGProxy *proxy;
334
 
   gboolean locked = FALSE;
335
 
  
336
 
   error = NULL;
337
 
   connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
338
 
   if (connection == NULL) {
339
 
      g_debug_update ("Failed to open connection to bus: %s\n", error->message);
340
 
      g_error_free (error);
341
 
      return FALSE;
342
 
   }
343
 
 
344
 
  proxy = dbus_g_proxy_new_for_name (connection,
345
 
                                     "com.ubuntu.SystemService",
346
 
                                     "/",
347
 
                                     "com.ubuntu.SystemService");
348
 
  error = NULL;
349
 
  if (!dbus_g_proxy_call (proxy, "is_package_system_locked", &error, 
350
 
                          G_TYPE_INVALID,
351
 
                          G_TYPE_BOOLEAN, &locked, G_TYPE_INVALID)) {
352
 
     g_debug_update ("error during dbus call: %s\n", error->message);
353
 
     g_error_free (error);
354
 
     g_object_unref (proxy);
355
 
     return FALSE;
356
 
  }
357
 
  g_object_unref (proxy);
358
 
 
359
 
  g_debug_update ("is_package_system_locked: %i", locked);
360
 
  return locked;
 
304
    gchar *cmd[] = { "pkexec", PACKAGE_SYSTEM_LOCKED, NULL };
 
305
    gint exit_status;
 
306
    GError *err = NULL;
 
307
 
 
308
    if(!g_spawn_sync(NULL, cmd, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL,
 
309
                NULL, NULL, NULL, NULL, &exit_status, &err)) {
 
310
        g_warning("failed to run " PACKAGE_SYSTEM_LOCKED ": %s", err->message);
 
311
        g_error_free(err);
 
312
        return FALSE;
 
313
    }
 
314
 
 
315
    if(!WIFEXITED(exit_status)) {
 
316
        g_warning(PACKAGE_SYSTEM_LOCKED " exited abnormally with code %i", exit_status);
 
317
        return FALSE;
 
318
    }
 
319
 
 
320
    exit_status = WEXITSTATUS(exit_status);
 
321
    g_debug_update ("is_package_system_locked: " PACKAGE_SYSTEM_LOCKED "returned %i", exit_status);
 
322
    return exit_status == 2;
361
323
}
362
324
 
363
325
#if 0
364
326
// ask devicekit.Power if we run on battery
365
327
static gboolean
366
 
running_on_battery ()
 
328
running_on_battery (void)
367
329
{
368
330
   DBusGConnection *connection;
369
331
   GError *error;
373
335
   error = NULL;
374
336
   connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
375
337
   if (connection == NULL) {
376
 
      g_debug_update ("Failed to open connection to bus: %s\n", error->message);
 
338
      g_debug_update ("Failed to open connection to bus: %s", error->message);
377
339
      g_error_free (error);
378
340
      return FALSE;
379
341
   }
389
351
                          G_TYPE_INVALID,
390
352
                          G_TYPE_BOOLEAN, &on_battery, 
391
353
                          G_TYPE_INVALID)) {
392
 
     g_debug_update ("failed Get dbus call: %s\n", 
 
354
     g_debug_update ("failed Get dbus call: %s", 
393
355
                     error?error->message:"no error given");
394
356
     if(error)
395
357
        g_error_free (error);
401
363
#endif
402
364
 
403
365
static gboolean
404
 
security_updates_are_installed_unattended()
 
366
security_updates_are_installed_unattended(void)
405
367
{
406
368
   int ret;
407
369
   GError *error = NULL;
418
380
 
419
381
      if (g_spawn_sync("/", cmd, NULL, 0, NULL, NULL, 
420
382
                       NULL, NULL, &ret, &error)) {
421
 
         g_debug("--security-updates-unattended: %i\n", WEXITSTATUS(ret));
 
383
         g_debug("--security-updates-unattended: %i", WEXITSTATUS(ret));
422
384
         if( WEXITSTATUS(ret) > 0 )
423
385
            return TRUE;
424
386
      } else if (error) {
437
399
                         time_t last_launch)
438
400
{
439
401
 
440
 
   // no security updates
441
 
   if (priv->num_security == 0)
 
402
   // no security updates and no reboot pending
 
403
   if ((priv->num_security == 0) && !priv->reboot_pending)
442
404
      return FALSE;
443
405
         
444
406
   // security updates, but already launched recently
445
407
   if ((last_launch + AUTOLAUNCH_MINIMAL_SECURITY_INTERVAL) > now) {
446
408
      g_debug_update("security updates, but update-manager was launched "
447
 
                     "within the AUTOLAUNCH_MINIMAL_SECURITY_INTERVAL\n");
 
409
                     "within the AUTOLAUNCH_MINIMAL_SECURITY_INTERVAL");
448
410
      return FALSE;
449
411
   }
450
412
   
457
419
   return TRUE;
458
420
}
459
421
 
 
422
// Like ctime, but without the annoying trailing newline.  Caller must
 
423
// g_free the result.
 
424
static gchar *
 
425
readable_timestamp(time_t time)
 
426
{
 
427
   GDateTime *datetime;
 
428
   gchar *formatted;
 
429
 
 
430
   datetime = g_date_time_new_from_unix_local (time);
 
431
   formatted = g_date_time_format (datetime, "%a %b %e %T %Y");
 
432
   g_date_time_unref (datetime);
 
433
   return formatted;
 
434
}
 
435
 
460
436
// check the logs of dpkg and apt for timestamps, the idea
461
437
// is to not auto launch if dpkg/apt were run manually by the
462
438
// user
463
439
static time_t
464
 
newest_log_file_timestamp()
 
440
newest_log_file_timestamp(void)
465
441
{
466
442
   struct stat buf;
467
443
   int i, j;
475
451
   {
476
452
      glob_t pglob;
477
453
      if(glob(log_glob[i], 0, NULL, &pglob) != 0) {
478
 
         g_warning("error from glob %s\n", log_glob[i]);
 
454
         g_warning("error from glob %s", log_glob[i]);
479
455
         continue;
480
456
      }
481
457
      for(j=0;j < pglob.gl_pathc; j++) {
482
 
 
483
458
         const char *log = pglob.gl_pathv[j];
 
459
         time_t mtime;
 
460
         gchar *timestamp;
 
461
 
484
462
         if(g_stat(log, &buf) <0) {
485
 
            g_warning("can't stat %s\n", log);
 
463
            g_warning("can't stat %s", log);
486
464
            continue;
487
465
         }
488
466
         if(buf.st_size == 0) {
489
 
            g_warning("log file empty (logrotate?) %s\n", log);
 
467
            g_warning("log file empty (logrotate?) %s", log);
490
468
            continue;
491
469
         }
492
 
         time_t mtime = buf.st_mtime;
493
 
         g_debug_update ("mtime from %s: %i (%s)\n", log, mtime, ctime(&mtime));
494
 
         time_t bctime = buf.st_ctime;
495
 
         g_debug_update ("ctime from %s: %i (%s)\n", log, bctime, ctime(&bctime));
496
 
         newest_log_stamp = MAX(MAX(mtime, bctime), newest_log_stamp);
497
 
         g_debug_update ("last_launch from %s: %i (%s)\n", log, newest_log_stamp, ctime(&newest_log_stamp));
 
470
 
 
471
         mtime = buf.st_mtime;
 
472
         timestamp = readable_timestamp (mtime);
 
473
         g_debug_update ("mtime from %s: %i (%s)", log, mtime, timestamp);
 
474
         g_free (timestamp);
 
475
 
 
476
         newest_log_stamp = MAX(mtime, newest_log_stamp);
 
477
         timestamp = readable_timestamp (newest_log_stamp);
 
478
         g_debug_update ("last_launch from %s: %i (%s)", log, newest_log_stamp, timestamp);
 
479
         g_free (timestamp);
498
480
      }
499
481
      globfree(&pglob);
500
482
   }
505
487
// time to launch again and if the dpkg lock is currently 
506
488
// not taken
507
489
static gboolean 
508
 
auto_launch_now (UpdateTrayAppletPrivate *priv)
 
490
auto_launch_now (TrayApplet *ta)
509
491
{
 
492
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
510
493
   int interval_days = 0;
511
494
   time_t last_launch = 0;
512
495
 
520
503
#endif
521
504
 
522
505
   // when checking for regular updates honor the 
523
 
   // regular_auto_launch_interval
524
 
   interval_days = gconf_client_get_int(priv->gconf,
525
 
                                        GCONF_KEY_AUTO_LAUNCH_INTERVAL, 
526
 
                                        NULL);
527
 
   g_debug_update ("interval_days from gconf: %i\n", interval_days);
 
506
   // regular-auto-launch-interval
 
507
   interval_days = g_settings_get_int(ta->un->settings,
 
508
                                        SETTINGS_KEY_AUTO_LAUNCH_INTERVAL);
 
509
   g_debug_update ("interval_days: %i", interval_days);
528
510
 
529
511
   if (interval_days <= 0) 
530
512
      return TRUE;
531
513
 
532
514
   // check last launch time 
533
 
   last_launch = gconf_client_get_int(priv->gconf,
534
 
                                      GCONF_KEY_LAST_LAUNCH,
535
 
                                      NULL);
536
 
   g_debug_update ("last_launch from gconf: %i (%s)\n", last_launch, ctime(&last_launch));
 
515
   GSettings *um_settings = g_settings_new(SETTINGS_UM_SCHEMA);
 
516
   last_launch = g_settings_get_int64(um_settings,
 
517
                                      SETTINGS_UM_KEY_LAST_LAUNCH);
 
518
   g_debug_update ("last_launch: %i (%s)", last_launch, ctime(&last_launch));
 
519
   g_object_unref(um_settings);
537
520
 
538
521
   time_t now = time(NULL);
539
522
   if (auto_launch_security_now(priv, now, last_launch))
540
523
      return TRUE;
541
524
 
542
 
   time_t log_files = newest_log_file_timestamp();
543
 
   last_launch = MAX(log_files, last_launch);
544
 
 
545
525
   g_debug_update("time now %i (%s), delta: %i", now, ctime(&now), now-last_launch);
546
526
   if ((last_launch + (24*60*60*interval_days)) < now) {
547
527
      g_debug_update ("need to auto launch");
557
537
   if(ta == NULL)
558
538
      return FALSE;
559
539
 
560
 
   g_debug_update ("update_check()\n");
 
540
   g_debug_update ("update_check()");
561
541
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
562
542
 
563
543
   priv->num_upgrades = 0;
564
544
   priv->num_security = 0;
 
545
   priv->reboot_pending = FALSE;
565
546
   int exit_status = 0;
566
547
   GError *error = NULL;
567
548
 
570
551
                   UPGRADE_CHECKER, 
571
552
                   NULL };
572
553
   char *ret;
 
554
   struct stat buf;
573
555
 
574
556
   if(g_spawn_sync(NULL, cmd, NULL,  
575
557
                   G_SPAWN_STDOUT_TO_DEV_NULL, 
593
575
                                      "Package Manager from the "
594
576
                                      "right-click menu or apt-get in "
595
577
                                      "a terminal to see what is wrong.\n"
596
 
                                      "The error message was: '%s'"),
 
578
                                      "The error message was: '%s'. "),
597
579
                                    &ret[2]);
598
580
         else
599
581
            g_string_append(error, _("An error occurred, please run "
627
609
   
628
610
   g_debug_update("%s returned %i (security: %i)", UPGRADE_CHECKER, priv->num_upgrades, priv->num_security);
629
611
 
630
 
   if (priv->num_upgrades == 0) {
 
612
   if (stat("/run/reboot-required", &buf) == 0) {
 
613
      priv->reboot_pending = TRUE;
 
614
      g_debug_update("A reboot is currently pending.");
 
615
   }
631
616
 
 
617
   if ((priv->num_upgrades == 0) && !priv->reboot_pending) {
632
618
      // check if the periodic file is very old
633
 
      struct stat buf;
634
619
      if ((stat("/var/lib/apt/periodic/update-success-stamp", &buf) == 0) &&
635
620
          (time(NULL) - buf.st_mtime > OUTDATED_NAG_AGE) ) 
636
621
         g_timeout_add_seconds(OUTDATED_NAG_WAIT, (GSourceFunc)outdated_nag, ta);
637
622
 
638
 
      gtk_status_icon_set_visible (ta->tray_icon, FALSE);
639
 
      
 
623
      tray_applet_ui_set_visible (ta, FALSE);
640
624
      if(priv->active_notification != NULL) {
641
625
         notify_notification_close(priv->active_notification, NULL);
642
 
         priv->active_notification = NULL; 
 
626
         g_clear_object(&priv->active_notification);
643
627
      }
644
628
      return TRUE;
645
629
   } 
648
632
      ta->name = "software-update-available";
649
633
   else
650
634
      ta->name = "software-update-urgent";
651
 
   gtk_status_icon_set_from_icon_name(ta->tray_icon, ta->name);
 
635
   tray_applet_ui_set_icon(ta, ta->name);
652
636
 
653
637
   // update the tooltip
654
638
   update_trayicon_update_tooltip(ta, priv->num_upgrades);
655
639
 
656
 
   // check if the user wants to see the icon or launch
657
 
   // the default action
658
 
   if(gconf_client_get_bool(priv->gconf,
659
 
                            GCONF_KEY_AUTO_LAUNCH, NULL)) 
 
640
   tray_applet_ui_set_visible(ta, FALSE);
 
641
   if (auto_launch_now(ta))
660
642
   {
661
 
      gtk_status_icon_set_visible(ta->tray_icon, FALSE);
662
 
      if (auto_launch_now(priv)) 
663
 
      {
664
 
         g_spawn_command_line_async("nice ionice -c3 update-manager "
665
 
                                    "--no-focus-on-map", NULL);
666
 
      }
667
 
      return TRUE;
 
643
      g_spawn_command_line_async("nice ionice -c3 update-manager "
 
644
                                 "--no-update --no-focus-on-map", NULL);
668
645
   }
 
646
   return TRUE;
669
647
 
670
648
   // if we are already visible, skip the rest
671
 
   if(gtk_status_icon_get_visible (ta->tray_icon))
 
649
   if(tray_applet_ui_get_visible (ta))
672
650
      return TRUE;
673
651
 
674
652
   // show the icon
675
 
   gtk_status_icon_set_visible(ta->tray_icon, TRUE);
 
653
   tray_applet_ui_set_visible(ta, TRUE);
676
654
   
677
655
   // the user does not no notification messages
678
 
   if(gconf_client_get_bool(priv->gconf,
679
 
                            GCONF_KEY_NO_UPDATE_NOTIFICATIONS, NULL))
 
656
   if(g_settings_get_boolean(ta->un->settings,
 
657
                             SETTINGS_KEY_NO_UPDATE_NOTIFICATIONS))
680
658
      return TRUE;
681
659
 
682
660
   // show the notification with some delay. otherwise on a login
692
670
{
693
671
   // create the private data struct
694
672
   UpdateTrayAppletPrivate *priv = g_new0(UpdateTrayAppletPrivate, 1);
695
 
   priv->gconf = gconf_client_get_default();
696
673
   priv->apt_is_running = FALSE;
697
674
   priv->active_notification = NULL;
698
675
   ta->user_data = priv;
699
676
 
700
 
   // connect the signals we need
 
677
   // create the indicator/icon immediately; we use this enough that it
 
678
   // probably isn't worth trying to save memory by avoiding it
 
679
   tray_applet_ui_ensure (ta);
 
680
 
 
681
#ifndef HAVE_APP_INDICATOR
 
682
   // the default action for the gtk_status_icon
701
683
   g_signal_connect (G_OBJECT(ta->tray_icon),
702
684
                     "activate",
703
 
                     G_CALLBACK (activate_cb),
704
 
                     ta);
705
 
   g_signal_connect (G_OBJECT(ta->tray_icon),
706
 
                     "popup-menu",
707
 
                     G_CALLBACK (popup_cb),
708
 
                     ta);
 
685
                     G_CALLBACK (gtk_status_icon_click_activate_cb),
 
686
                     ta);
 
687
#endif
709
688
 
710
689
   /* Menu initialization */
711
690
   update_trayicon_create_menu (ta);
 
691
   tray_applet_ui_set_menu (ta, ta->menu);
712
692
   
713
693
   /* Check for updates for the first time */
714
694
   update_check (ta);