static gboolean schedule_wakeups_with_timerfd (GoaAlarm *self) { #ifdef HAVE_TIMERFD struct itimerspec timer_spec; int fd; int result; GSource *source; static gboolean seen_before = FALSE; if (!seen_before) { goa_debug ("GoaAlarm: trying to use kernel timer"); seen_before = TRUE; } fd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC | TFD_NONBLOCK); if (fd < 0) { goa_debug ("GoaAlarm: could not create timer fd: %m"); return FALSE; } memset (&timer_spec, 0, sizeof (timer_spec)); timer_spec.it_value.tv_sec = g_date_time_to_unix (self->priv->time) + 1; result = timerfd_settime (fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &timer_spec, NULL); if (result < 0) { goa_debug ("GoaAlarm: could not set timer: %m"); return FALSE; } self->priv->type = GOA_ALARM_TYPE_TIMER; self->priv->timer.stream = g_unix_input_stream_new (fd, TRUE); source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (self->priv->timer.stream), self->priv->cancellable); self->priv->timer.source = source; g_source_set_callback (self->priv->timer.source, (GSourceFunc) on_timer_source_ready, self, (GDestroyNotify) clear_timer_source_pointer); g_source_attach (self->priv->timer.source, self->priv->context); g_source_unref (source); return TRUE; #endif /*HAVE_TIMERFD */ return FALSE; }
static void schedule_wakeups (GoaAlarm *self) { gboolean wakeup_scheduled; wakeup_scheduled = schedule_wakeups_with_timerfd (self); if (!wakeup_scheduled) { static gboolean seen_before = FALSE; if (!seen_before) { goa_debug ("GoaAlarm: falling back to polling timeout"); seen_before = TRUE; } schedule_wakeups_with_timeout_source (self); } }
static void process_config_entries (GoaDaemon *daemon, GHashTable *group_name_to_key_file_data) { GHashTableIter iter; const gchar *id; KeyFileData *key_file_data; GList *existing_object_paths; GList *config_object_paths; GList *added; GList *removed; GList *unchanged; GList *l; existing_object_paths = NULL; { GList *existing_objects; existing_objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (daemon->object_manager)); for (l = existing_objects; l != NULL; l = l->next) { GoaObject *object = GOA_OBJECT (l->data); const gchar *object_path; object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object)); if (g_str_has_prefix (object_path, "/org/gnome/OnlineAccounts/Accounts/")) existing_object_paths = g_list_prepend (existing_object_paths, g_strdup (object_path)); } g_list_foreach (existing_objects, (GFunc) g_object_unref, NULL); g_list_free (existing_objects); } config_object_paths = NULL; g_hash_table_iter_init (&iter, group_name_to_key_file_data); while (g_hash_table_iter_next (&iter, (gpointer*) &id, (gpointer*) &key_file_data)) { gchar *object_path; /* create and validate object path */ object_path = g_strdup_printf ("/org/gnome/OnlineAccounts/Accounts/%s", id + sizeof "Account " - 1); if (strstr (id + sizeof "Account " - 1, "/") != NULL || !g_variant_is_object_path (object_path)) { goa_warning ("`%s' is not a valid account identifier", id); g_free (object_path); continue; } /* steals object_path variable */ config_object_paths = g_list_prepend (config_object_paths, object_path); } existing_object_paths = g_list_sort (existing_object_paths, (GCompareFunc) g_strcmp0); config_object_paths = g_list_sort (config_object_paths, (GCompareFunc) g_strcmp0); diff_sorted_lists (existing_object_paths, config_object_paths, (GCompareFunc) g_strcmp0, &added, &removed, &unchanged); for (l = removed; l != NULL; l = l->next) { const gchar *object_path = l->data; GoaObject *object; object = GOA_OBJECT (g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (daemon->object_manager), object_path)); g_warn_if_fail (object != NULL); g_signal_handlers_disconnect_by_func (goa_object_peek_account (object), G_CALLBACK (account_on_attention_needed_notify), daemon); g_signal_handlers_disconnect_by_func (goa_object_peek_account (object), G_CALLBACK (on_account_handle_remove), daemon); goa_debug ("removing %s", object_path); g_warn_if_fail (g_dbus_object_manager_server_unexport (daemon->object_manager, object_path)); } for (l = added; l != NULL; l = l->next) { const gchar *object_path = l->data; GoaObjectSkeleton *object; gchar *group; goa_debug ("adding %s", object_path); group = object_path_to_group (object_path); key_file_data = g_hash_table_lookup (group_name_to_key_file_data, group); g_warn_if_fail (key_file_data != NULL); object = goa_object_skeleton_new (object_path); if (update_account_object (daemon, object, key_file_data->path, group, key_file_data->key_file, TRUE)) { g_dbus_object_manager_server_export (daemon->object_manager, G_DBUS_OBJECT_SKELETON (object)); g_signal_connect (goa_object_peek_account (GOA_OBJECT (object)), "notify::attention-needed", G_CALLBACK (account_on_attention_needed_notify), daemon); g_signal_connect (goa_object_peek_account (GOA_OBJECT (object)), "handle-remove", G_CALLBACK (on_account_handle_remove), daemon); g_signal_connect (goa_object_peek_account (GOA_OBJECT (object)), "handle-ensure-credentials", G_CALLBACK (on_account_handle_ensure_credentials), daemon); } g_object_unref (object); g_free (group); } for (l = unchanged; l != NULL; l = l->next) { const gchar *object_path = l->data; GoaObject *object; gchar *group; goa_debug ("unchanged %s", object_path); group = object_path_to_group (object_path); key_file_data = g_hash_table_lookup (group_name_to_key_file_data, group); g_warn_if_fail (key_file_data != NULL); object = GOA_OBJECT (g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (daemon->object_manager), object_path)); g_warn_if_fail (object != NULL); if (!update_account_object (daemon, GOA_OBJECT_SKELETON (object), key_file_data->path, group, key_file_data->key_file, FALSE)) { g_signal_handlers_disconnect_by_func (goa_object_peek_account (object), G_CALLBACK (account_on_attention_needed_notify), daemon); g_signal_handlers_disconnect_by_func (goa_object_peek_account (object), G_CALLBACK (on_account_handle_remove), daemon); g_signal_handlers_disconnect_by_func (goa_object_peek_account (object), G_CALLBACK (on_account_handle_ensure_credentials), daemon); g_warn_if_fail (g_dbus_object_manager_server_unexport (daemon->object_manager, object_path)); } g_object_unref (object); g_free (group); } g_list_free (removed); g_list_free (added); g_list_free (unchanged); g_list_foreach (existing_object_paths, (GFunc) g_free, NULL); g_list_free (existing_object_paths); g_list_foreach (config_object_paths, (GFunc) g_free, NULL); g_list_free (config_object_paths); }
/* returns FALSE if object is not (or no longer) valid */ static gboolean update_account_object (GoaDaemon *daemon, GoaObjectSkeleton *object, const gchar *path, const gchar *group, GKeyFile *key_file, gboolean just_added) { GoaAccount *account; GoaProvider *provider; gboolean ret; gchar *identity; gchar *presentation_identity; gchar *type; gchar *name; GIcon *icon; gchar *serialized_icon; GError *error; g_return_val_if_fail (GOA_IS_DAEMON (daemon), FALSE); g_return_val_if_fail (G_IS_DBUS_OBJECT_SKELETON (object), FALSE); g_return_val_if_fail (group != NULL, FALSE); g_return_val_if_fail (key_file != NULL, FALSE); ret = FALSE; identity = NULL; type = NULL; account = NULL; name = NULL; icon = NULL; serialized_icon = NULL; goa_debug ("updating %s %d", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)), just_added); type = g_key_file_get_string (key_file, group, "Provider", NULL); identity = g_key_file_get_string (key_file, group, "Identity", NULL); presentation_identity = g_key_file_get_string (key_file, group, "PresentationIdentity", NULL); if (just_added) { account = goa_account_skeleton_new (); goa_object_skeleton_set_account (object, account); } else { account = goa_object_get_account (GOA_OBJECT (object)); } provider = goa_provider_get_for_provider_type (type); if (provider == NULL) { goa_warning ("Unsupported account type %s for identity %s (no provider)", type, identity); goto out; } name = goa_provider_get_provider_name (provider, GOA_OBJECT (object)); icon = goa_provider_get_provider_icon (provider, GOA_OBJECT (object)); serialized_icon = g_icon_to_string (icon); goa_account_set_id (account, g_strrstr (g_dbus_object_get_object_path (G_DBUS_OBJECT (object)), "/") + 1); goa_account_set_provider_type (account, type); goa_account_set_provider_name (account, name); goa_account_set_provider_icon (account, serialized_icon); goa_account_set_identity (account, identity); goa_account_set_presentation_identity (account, presentation_identity); error = NULL; if (!goa_provider_build_object (provider, object, key_file, group, &error)) { goa_warning ("Error parsing account: %s (%s, %d)", error->message, g_quark_to_string (error->domain), error->code); g_error_free (error); goto out; } ret = TRUE; out: g_free (serialized_icon); if (icon != NULL) g_object_unref (icon); g_free (name); if (provider != NULL) g_object_unref (provider); g_object_unref (account); g_free (type); g_free (identity); return ret; }