1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3
* Copyright (C) 2007-2011 Richard Hughes <richard@hughsie.com>
5
* Licensed under the GNU General Public License Version 2
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
#include <glib/gi18n.h>
25
#include <packagekit-glib2/packagekit.h>
26
#include <libupower-glib/upower.h>
28
#include "gnome-settings-bus.h"
30
#include "gsd-updates-common.h"
31
#include "gsd-updates-refresh.h"
33
static void gsd_updates_refresh_finalize (GObject *object);
35
#define GSD_UPDATES_REFRESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_UPDATES_REFRESH, GsdUpdatesRefreshPrivate))
37
#define PERIODIC_CHECK_TIME 60*60 /* poke PackageKit every hour */
38
#define LOGIN_TIMEOUT 3 /* seconds */
39
#define SESSION_STARTUP_TIMEOUT 10 /* seconds */
42
PRESENCE_STATUS_AVAILABLE = 0,
43
PRESENCE_STATUS_INVISIBLE,
46
PRESENCE_STATUS_UNKNOWN
50
* at startup, after a small delay, force a GetUpdates call
51
* every hour (or any event) check:
52
- if we are online, idle and on AC power, it's been more than a day
53
since we refreshed then RefreshCache
54
- if we are online and it's been longer than the timeout since
55
getting the updates period then GetUpdates
58
struct GsdUpdatesRefreshPrivate
60
gboolean session_idle;
62
gboolean network_active;
67
GsdSessionManager *proxy_session;
78
static guint signals [LAST_SIGNAL] = { 0 };
80
G_DEFINE_TYPE (GsdUpdatesRefresh, gsd_updates_refresh, G_TYPE_OBJECT)
83
gsd_updates_refresh_class_init (GsdUpdatesRefreshClass *klass)
85
GObjectClass *object_class = G_OBJECT_CLASS (klass);
86
object_class->finalize = gsd_updates_refresh_finalize;
87
g_type_class_add_private (klass, sizeof (GsdUpdatesRefreshPrivate));
88
signals [REFRESH_CACHE] =
89
g_signal_new ("refresh-cache",
90
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
91
0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
93
signals [GET_UPDATES] =
94
g_signal_new ("get-updates",
95
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
96
0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
98
signals [GET_UPGRADES] =
99
g_signal_new ("get-upgrades",
100
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
101
0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
106
get_time_refresh_cache_cb (GObject *object,
108
GsdUpdatesRefresh *refresh)
110
PkControl *control = PK_CONTROL (object);
111
GError *error = NULL;
116
seconds = pk_control_get_time_since_action_finish (control, res, &error);
118
g_warning ("failed to get time: %s", error->message);
119
g_error_free (error);
123
/* have we passed the timout? */
124
thresh = g_settings_get_int (refresh->priv->settings,
125
GSD_SETTINGS_FREQUENCY_GET_UPDATES);
126
if (seconds < thresh) {
127
g_debug ("not before timeout, thresh=%u, now=%u", thresh, seconds);
132
g_debug ("emitting refresh-cache");
133
g_signal_emit (refresh, signals [REFRESH_CACHE], 0);
137
maybe_refresh_cache (GsdUpdatesRefresh *refresh)
141
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
143
/* if we don't want to auto check for updates, don't do this either */
144
thresh = g_settings_get_int (refresh->priv->settings,
145
GSD_SETTINGS_FREQUENCY_GET_UPDATES);
147
g_debug ("not when policy is set to never");
151
/* only do the refresh cache when the user is idle */
152
if (!refresh->priv->session_idle) {
153
g_debug ("not when session active");
157
/* get this each time, as it may have changed behind out back */
158
thresh = g_settings_get_int (refresh->priv->settings,
159
GSD_SETTINGS_FREQUENCY_REFRESH_CACHE);
161
g_debug ("not when policy is set to never");
165
/* get the time since the last refresh */
166
pk_control_get_time_since_action_async (refresh->priv->control,
167
PK_ROLE_ENUM_REFRESH_CACHE,
169
(GAsyncReadyCallback) get_time_refresh_cache_cb,
174
get_time_get_updates_cb (GObject *object, GAsyncResult *res, GsdUpdatesRefresh *refresh)
176
PkControl *control = PK_CONTROL (object);
177
GError *error = NULL;
182
seconds = pk_control_get_time_since_action_finish (control, res, &error);
184
g_warning ("failed to get time: %s", error->message);
185
g_error_free (error);
189
/* have we passed the timout? */
190
thresh = g_settings_get_int (refresh->priv->settings,
191
GSD_SETTINGS_FREQUENCY_GET_UPDATES);
192
if (seconds < thresh) {
193
g_debug ("not before timeout, thresh=%u, now=%u", thresh, seconds);
198
g_debug ("emitting get-updates");
199
g_signal_emit (refresh, signals [GET_UPDATES], 0);
203
maybe_get_updates (GsdUpdatesRefresh *refresh)
207
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
209
/* if we don't want to auto check for updates, don't do this either */
210
thresh = g_settings_get_int (refresh->priv->settings,
211
GSD_SETTINGS_FREQUENCY_GET_UPDATES);
213
g_debug ("not when policy is set to never");
217
/* get the time since the last refresh */
218
pk_control_get_time_since_action_async (refresh->priv->control,
219
PK_ROLE_ENUM_GET_UPDATES,
221
(GAsyncReadyCallback) get_time_get_updates_cb,
226
get_time_get_upgrades_cb (GObject *object,
228
GsdUpdatesRefresh *refresh)
230
PkControl *control = PK_CONTROL (object);
231
GError *error = NULL;
236
seconds = pk_control_get_time_since_action_finish (control, res, &error);
238
g_warning ("failed to get time: %s", error->message);
239
g_error_free (error);
243
/* have we passed the timout? */
244
thresh = g_settings_get_int (refresh->priv->settings,
245
GSD_SETTINGS_FREQUENCY_GET_UPDATES);
246
if (seconds < thresh) {
247
g_debug ("not before timeout, thresh=%u, now=%u",
253
g_debug ("emitting get-upgrades");
254
g_signal_emit (refresh, signals [GET_UPGRADES], 0);
258
maybe_get_upgrades (GsdUpdatesRefresh *refresh)
262
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
264
/* get this each time, as it may have changed behind out back */
265
thresh = g_settings_get_int (refresh->priv->settings,
266
GSD_SETTINGS_FREQUENCY_GET_UPGRADES);
268
g_debug ("not when policy is set to never");
272
/* get the time since the last refresh */
273
pk_control_get_time_since_action_async (refresh->priv->control,
274
PK_ROLE_ENUM_GET_DISTRO_UPGRADES,
276
(GAsyncReadyCallback) get_time_get_upgrades_cb,
281
change_state_cb (GsdUpdatesRefresh *refresh)
283
/* check all actions */
284
maybe_refresh_cache (refresh);
285
maybe_get_updates (refresh);
286
maybe_get_upgrades (refresh);
291
change_state (GsdUpdatesRefresh *refresh)
295
g_return_val_if_fail (GSD_IS_UPDATES_REFRESH (refresh), FALSE);
297
/* no point continuing if we have no network */
298
if (!refresh->priv->network_active) {
299
g_debug ("not when no network");
303
/* not on battery unless overridden */
304
ret = g_settings_get_boolean (refresh->priv->settings,
305
GSD_SETTINGS_UPDATE_BATTERY);
306
if (!ret && refresh->priv->on_battery) {
307
g_debug ("not when on battery");
311
/* wait a little time for things to settle down */
312
if (refresh->priv->timeout_id != 0)
313
g_source_remove (refresh->priv->timeout_id);
314
g_debug ("defering action for %i seconds",
315
SESSION_STARTUP_TIMEOUT);
316
refresh->priv->timeout_id =
317
g_timeout_add_seconds (SESSION_STARTUP_TIMEOUT,
318
(GSourceFunc) change_state_cb,
320
g_source_set_name_by_id (refresh->priv->timeout_id,
321
"[GsdUpdatesRefresh] change-state");
327
settings_key_changed_cb (GSettings *client,
329
GsdUpdatesRefresh *refresh)
331
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
332
if (g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_GET_UPDATES) == 0 ||
333
g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_GET_UPGRADES) == 0 ||
334
g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_REFRESH_CACHE) == 0 ||
335
g_strcmp0 (key, GSD_SETTINGS_UPDATE_BATTERY) == 0)
336
change_state (refresh);
340
convert_network_state (GsdUpdatesRefresh *refresh, PkNetworkEnum state)
343
if (state == PK_NETWORK_ENUM_OFFLINE)
347
if (state == PK_NETWORK_ENUM_ONLINE ||
348
state == PK_NETWORK_ENUM_WIFI ||
349
state == PK_NETWORK_ENUM_WIRED)
353
if (state == PK_NETWORK_ENUM_MOBILE)
354
return g_settings_get_boolean (refresh->priv->settings,
355
GSD_SETTINGS_CONNECTION_USE_MOBILE);
358
g_warning ("state unknown: %i", state);
363
notify_network_state_cb (PkControl *control,
365
GsdUpdatesRefresh *refresh)
369
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
371
g_object_get (control, "network-state", &state, NULL);
372
refresh->priv->network_active = convert_network_state (refresh, state);
373
g_debug ("setting online %i", refresh->priv->network_active);
374
if (refresh->priv->network_active)
375
change_state (refresh);
379
periodic_timeout_cb (gpointer user_data)
381
GsdUpdatesRefresh *refresh = GSD_UPDATES_REFRESH (user_data);
383
g_return_val_if_fail (GSD_IS_UPDATES_REFRESH (refresh), FALSE);
385
/* debug so we can catch polling */
386
g_debug ("polling check");
388
/* triggered once an hour */
389
change_state (refresh);
396
gsd_updates_refresh_client_changed_cb (UpClient *client,
397
GsdUpdatesRefresh *refresh)
401
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
403
/* get the on-battery state */
404
on_battery = up_client_get_on_battery (refresh->priv->client);
405
if (on_battery == refresh->priv->on_battery) {
406
g_debug ("same state as before, ignoring");
410
/* save in local cache */
411
g_debug ("setting on_battery %i", on_battery);
412
refresh->priv->on_battery = on_battery;
414
change_state (refresh);
418
get_properties_cb (GObject *object,
420
GsdUpdatesRefresh *refresh)
423
GError *error = NULL;
424
PkControl *control = PK_CONTROL(object);
428
ret = pk_control_get_properties_finish (control, res, &error);
430
/* TRANSLATORS: backend is broken, and won't tell us what it supports */
431
g_warning ("could not get properties");
432
g_error_free (error);
437
g_object_get (control,
438
"network-state", &state,
440
refresh->priv->network_active = convert_network_state (refresh, state);
446
session_presence_signal_cb (GDBusProxy *proxy,
449
GVariant *parameters,
450
GsdUpdatesRefresh *refresh)
454
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
456
if (g_strcmp0 (signal_name, "StatusChanged") != 0)
459
/* map status code into boolean */
460
g_variant_get (parameters, "(u)", &status);
461
refresh->priv->session_idle = (status == PRESENCE_STATUS_IDLE);
462
g_debug ("setting is_idle %i",
463
refresh->priv->session_idle);
464
if (refresh->priv->session_idle)
465
change_state (refresh);
470
gsd_updates_refresh_init (GsdUpdatesRefresh *refresh)
475
refresh->priv = GSD_UPDATES_REFRESH_GET_PRIVATE (refresh);
476
refresh->priv->on_battery = FALSE;
477
refresh->priv->network_active = FALSE;
478
refresh->priv->timeout_id = 0;
479
refresh->priv->periodic_id = 0;
481
/* we need to know the updates frequency */
482
refresh->priv->settings = g_settings_new (GSD_SETTINGS_SCHEMA);
483
g_signal_connect (refresh->priv->settings, "changed",
484
G_CALLBACK (settings_key_changed_cb), refresh);
486
/* we need to query the last cache refresh time */
487
refresh->priv->control = pk_control_new ();
488
g_signal_connect (refresh->priv->control, "notify::network-state",
489
G_CALLBACK (notify_network_state_cb),
492
/* get network state */
493
pk_control_get_properties_async (refresh->priv->control,
495
(GAsyncReadyCallback) get_properties_cb,
499
refresh->priv->client = up_client_new ();
500
g_signal_connect (refresh->priv->client, "changed",
501
G_CALLBACK (gsd_updates_refresh_client_changed_cb), refresh);
503
/* get the battery state */
504
refresh->priv->on_battery = up_client_get_on_battery (refresh->priv->client);
505
g_debug ("setting on battery %i", refresh->priv->on_battery);
507
/* use gnome-session for the idle detection */
508
refresh->priv->proxy_session =
509
gnome_settings_bus_get_session_proxy ();
510
if (refresh->priv->proxy_session != NULL) {
511
g_signal_connect (G_DBUS_PROXY (refresh->priv->proxy_session),
513
G_CALLBACK (session_presence_signal_cb),
515
status = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (refresh->priv->proxy_session),
518
g_variant_get (status, "u", &status_code);
519
refresh->priv->session_idle = (status_code == PRESENCE_STATUS_IDLE);
520
g_variant_unref (status);
523
refresh->priv->session_idle = FALSE;
527
/* we check this in case we miss one of the async signals */
528
refresh->priv->periodic_id =
529
g_timeout_add_seconds (PERIODIC_CHECK_TIME,
530
periodic_timeout_cb, refresh);
531
g_source_set_name_by_id (refresh->priv->periodic_id,
532
"[GsdUpdatesRefresh] periodic check");
534
/* check system state */
535
change_state (refresh);
539
gsd_updates_refresh_finalize (GObject *object)
541
GsdUpdatesRefresh *refresh;
543
g_return_if_fail (GSD_IS_UPDATES_REFRESH (object));
545
refresh = GSD_UPDATES_REFRESH (object);
546
g_return_if_fail (refresh->priv != NULL);
548
if (refresh->priv->timeout_id != 0)
549
g_source_remove (refresh->priv->timeout_id);
550
if (refresh->priv->periodic_id != 0)
551
g_source_remove (refresh->priv->periodic_id);
553
g_signal_handlers_disconnect_by_data (refresh->priv->client, refresh);
554
g_signal_handlers_disconnect_by_data (refresh->priv->proxy_session, refresh);
556
g_object_unref (refresh->priv->control);
557
g_object_unref (refresh->priv->settings);
558
g_object_unref (refresh->priv->client);
559
if (refresh->priv->proxy_session != NULL)
560
g_object_unref (refresh->priv->proxy_session);
562
G_OBJECT_CLASS (gsd_updates_refresh_parent_class)->finalize (object);
566
gsd_updates_refresh_new (void)
568
GsdUpdatesRefresh *refresh;
569
refresh = g_object_new (GSD_TYPE_UPDATES_REFRESH, NULL);
570
return GSD_UPDATES_REFRESH (refresh);