Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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);
    }
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
/* 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;
}