diff options
author | Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com> | 2012-06-30 14:54:48 +0200 |
---|---|---|
committer | Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com> | 2012-06-30 14:54:48 +0200 |
commit | 61208d0a4d41406aa70f44f963cd80e6b7127a0b (patch) | |
tree | a94108a3abca25814aa41b1c26b020f47dd5673f | |
parent | 5f39c94c64fa5cc051765df1f544f63caca49c07 (diff) |
Start writing Google Docs data-source
-rw-r--r-- | src/Makefile.am | 7 | ||||
-rw-r--r-- | src/gd-gdata-goa-authorizer.c | 539 | ||||
-rw-r--r-- | src/gd-gdata-goa-authorizer.h | 66 | ||||
-rw-r--r-- | src/google-authorizer.vapi | 5 | ||||
-rw-r--r-- | src/google-provider.vala | 68 | ||||
-rw-r--r-- | src/zeitgeist-datahub.vala | 1 |
6 files changed, 685 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index de5d208..7276047 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,11 @@ VALAFLAGS = \ --pkg json-glib-1.0 \ --pkg telepathy-glib \ --pkg zeitgeist-1.0 \ + --pkg goa-1.0 \ + --vapidir $(top_srcdir)/src \ + -X "-DGOA_API_IS_SUBJJECT_TO_CHANGE" \ glib-extra.vapi \ + google-authorizer.vapi \ $(top_srcdir)/config.vapi \ $(NULL) @@ -27,9 +31,9 @@ zeitgeist_datahub_SOURCES = \ kde-recent-document-provider.vala \ recent-manager-provider.vala \ telepathy-observer.vala \ + google-provider.vala \ utils.vala \ zeitgeist-datahub.vala \ - $(optional_zeitgeist_datahub_SOURCES) \ $(NULL) xdgautostart_in_files = \ @@ -44,4 +48,5 @@ CLEANFILES = zeitgeist-datahub.desktop EXTRA_DIST = \ glib-extra.vapi \ + google-authorizer.vapi \ $(xdgautostart_in_files) diff --git a/src/gd-gdata-goa-authorizer.c b/src/gd-gdata-goa-authorizer.c new file mode 100644 index 0000000..b4ede0e --- /dev/null +++ b/src/gd-gdata-goa-authorizer.c @@ -0,0 +1,539 @@ +/* + * e-gdata-goa-authorizer.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + */ + +#include "gd-gdata-goa-authorizer.h" + +#include <string.h> +#include <oauth.h> + +#define GD_GDATA_GOA_AUTHORIZER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), GD_TYPE_GDATA_GOA_AUTHORIZER, GdGDataGoaAuthorizerPrivate)) + +struct _GdGDataGoaAuthorizerPrivate { + + /* GDataAuthorizer methods must be thread-safe. */ + GMutex mutex; + + /* GoaObject is already thread-safe. */ + GoaObject *goa_object; + + /* These members are protected by the GMutex. */ + gchar *access_token; + gchar *access_token_secret; + GHashTable *authorization_domains; +}; + +enum { + PROP_0, + PROP_GOA_OBJECT +}; + +/* Forward Declarations */ +static void gd_gdata_goa_authorizer_interface_init + (GDataAuthorizerInterface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + GdGDataGoaAuthorizer, + gd_gdata_goa_authorizer, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE ( + GDATA_TYPE_AUTHORIZER, + gd_gdata_goa_authorizer_interface_init)) + +static GHashTable * +gdata_goa_authorizer_get_parameters (SoupMessage *message, + const gchar *consumer_key, + const gchar *consumer_secret, + const gchar *access_token, + const gchar *access_token_secret) +{ + GString *query; + GString *base_string; + GString *signing_key; + GHashTable *parameters; + GHashTable *hash_table; + GHashTableIter iter; + SoupURI *soup_uri; + GList *keys, *link; + gchar *string; + gchar *request_uri; + gpointer key, value; + + parameters = g_hash_table_new_full ( + (GHashFunc) g_str_hash, + (GEqualFunc) g_str_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) g_free); + + /* soup_form_decode() uses an awkward allocation style for + * its hash table entries, so it's easier to copy its content + * into our own hash table than try to use the returned hash + * table directly. */ + + soup_uri = soup_message_get_uri (message); + + if (soup_uri->query != NULL) { + hash_table = soup_form_decode (soup_uri->query); + g_hash_table_iter_init (&iter, hash_table); + while (g_hash_table_iter_next (&iter, &key, &value)) { + key = (gpointer) g_intern_string (key); + g_hash_table_insert (parameters, key, g_strdup (value)); + } + g_hash_table_destroy (hash_table); + } + + /* Add OAuth parameters. */ + + key = (gpointer) "oauth_version"; + g_hash_table_insert (parameters, key, g_strdup ("1.0")); + + string = oauth_gen_nonce (); + key = (gpointer) "oauth_nonce"; + g_hash_table_insert (parameters, key, g_strdup (string)); + free (string); /* do not use g_free () */ + + key = (gpointer) "oauth_timestamp"; + string = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) time (NULL)); + g_hash_table_insert (parameters, key, string); /* takes ownership */ + + key = (gpointer) "oauth_consumer_key"; + g_hash_table_insert (parameters, key, g_strdup (consumer_key)); + + key = (gpointer) "oauth_token"; + g_hash_table_insert (parameters, key, g_strdup (access_token)); + + key = (gpointer) "oauth_signature_method"; + g_hash_table_insert (parameters, key, g_strdup ("HMAC-SHA1")); + + /* Build the query part of the signature base string. */ + + query = g_string_sized_new (512); + keys = g_hash_table_get_keys (parameters); + keys = g_list_sort (keys, (GCompareFunc) g_strcmp0); + for (link = keys; link != NULL; link = g_list_next (link)) { + const gchar *key = link->data; + const gchar *val; + + val = g_hash_table_lookup (parameters, key); + + if (link != keys) + g_string_append_c (query, '&'); + + g_string_append_uri_escaped (query, key, NULL, FALSE); + g_string_append_c (query, '='); + g_string_append_uri_escaped (query, val, NULL, FALSE); + } + g_list_free (keys); + + /* Build the signature base string. */ + + soup_uri = soup_uri_copy (soup_uri); + soup_uri_set_query (soup_uri, NULL); + soup_uri_set_fragment (soup_uri, NULL); + request_uri = soup_uri_to_string (soup_uri, FALSE); + soup_uri_free (soup_uri); + + base_string = g_string_sized_new (512); + g_string_append_uri_escaped (base_string, message->method, NULL, FALSE); + g_string_append_c (base_string, '&'); + g_string_append_uri_escaped (base_string, request_uri, NULL, FALSE); + g_string_append_c (base_string, '&'); + g_string_append_uri_escaped (base_string, query->str, NULL, FALSE); + + /* Build the HMAC-SHA1 signing key. */ + + signing_key = g_string_sized_new (512); + g_string_append_uri_escaped ( + signing_key, consumer_secret, NULL, FALSE); + g_string_append_c (signing_key, '&'); + g_string_append_uri_escaped ( + signing_key, access_token_secret, NULL, FALSE); + + /* Sign the request. */ + + key = (gpointer) "oauth_signature"; + string = oauth_sign_hmac_sha1 (base_string->str, signing_key->str); + g_hash_table_insert (parameters, key, g_strdup (string)); + free (string); /* do not use g_free () */ + + g_free (request_uri); + + g_string_free (query, TRUE); + g_string_free (base_string, TRUE); + g_string_free (signing_key, TRUE); + + return parameters; +} + +static void +gdata_goa_authorizer_add_authorization (GDataAuthorizer *authorizer, + SoupMessage *message) +{ + GdGDataGoaAuthorizerPrivate *priv; + GoaOAuthBased *goa_oauth_based; + GHashTable *parameters; + GString *authorization; + const gchar *consumer_key; + const gchar *consumer_secret; + gint ii; + + const gchar *oauth_keys[] = { + "oauth_version", + "oauth_nonce", + "oauth_timestamp", + "oauth_consumer_key", + "oauth_token", + "oauth_signature_method", + "oauth_signature" + }; + + /* This MUST be called with the mutex already locked. */ + + priv = GD_GDATA_GOA_AUTHORIZER_GET_PRIVATE (authorizer); + + /* We can't add an Authorization header without an access token. + * Let the request fail. GData should refresh us if it gets back + * a "401 Authorization required" response from Google, and then + * automatically retry the request. */ + if (priv->access_token == NULL) + return; + + goa_oauth_based = goa_object_get_oauth_based (priv->goa_object); + + consumer_key = goa_oauth_based_get_consumer_key (goa_oauth_based); + consumer_secret = goa_oauth_based_get_consumer_secret (goa_oauth_based); + + parameters = gdata_goa_authorizer_get_parameters ( + message, + consumer_key, + consumer_secret, + priv->access_token, + priv->access_token_secret); + + authorization = g_string_new ("OAuth "); + + for (ii = 0; ii < G_N_ELEMENTS (oauth_keys); ii++) { + const gchar *key; + const gchar *val; + + key = oauth_keys[ii]; + val = g_hash_table_lookup (parameters, key); + + if (ii > 0) + g_string_append (authorization, ", "); + + g_string_append (authorization, key); + g_string_append_c (authorization, '='); + g_string_append_c (authorization, '"'); + g_string_append_uri_escaped (authorization, val, NULL, FALSE); + g_string_append_c (authorization, '"'); + } + + /* Use replace here, not append, to make sure + * there's only one "Authorization" header. */ + soup_message_headers_replace ( + message->request_headers, + "Authorization", authorization->str); + + g_string_free (authorization, TRUE); + g_hash_table_destroy (parameters); + + g_object_unref (goa_oauth_based); +} + +static gboolean +gdata_goa_authorizer_is_authorized (GDataAuthorizer *authorizer, + GDataAuthorizationDomain *domain) +{ + GdGDataGoaAuthorizerPrivate *priv; + + /* This MUST be called with the mutex already locked. */ + + if (domain == NULL) + return TRUE; + + priv = GD_GDATA_GOA_AUTHORIZER_GET_PRIVATE (authorizer); + domain = g_hash_table_lookup (priv->authorization_domains, domain); + + return (domain != NULL); +} + +static void +gdata_goa_authorizer_set_goa_object (GdGDataGoaAuthorizer *authorizer, + GoaObject *goa_object) +{ + g_return_if_fail (GOA_IS_OBJECT (goa_object)); + g_return_if_fail (authorizer->priv->goa_object == NULL); + + authorizer->priv->goa_object = g_object_ref (goa_object); +} + +static void +gdata_goa_authorizer_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_GOA_OBJECT: + gdata_goa_authorizer_set_goa_object ( + GD_GDATA_GOA_AUTHORIZER (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +gdata_goa_authorizer_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_GOA_OBJECT: + g_value_set_object ( + value, + gd_gdata_goa_authorizer_get_goa_object ( + GD_GDATA_GOA_AUTHORIZER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +gdata_goa_authorizer_dispose (GObject *object) +{ + GdGDataGoaAuthorizerPrivate *priv; + + priv = GD_GDATA_GOA_AUTHORIZER_GET_PRIVATE (object); + + if (priv->goa_object != NULL) { + g_object_unref (priv->goa_object); + priv->goa_object = NULL; + } + + g_hash_table_remove_all (priv->authorization_domains); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (gd_gdata_goa_authorizer_parent_class)->dispose (object); +} + +static void +gdata_goa_authorizer_finalize (GObject *object) +{ + GdGDataGoaAuthorizerPrivate *priv; + + priv = GD_GDATA_GOA_AUTHORIZER_GET_PRIVATE (object); + + g_mutex_clear (&priv->mutex); + g_free (priv->access_token); + g_free (priv->access_token_secret); + g_hash_table_destroy (priv->authorization_domains); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (gd_gdata_goa_authorizer_parent_class)->finalize (object); +} + +static void +gdata_goa_authorizer_constructed (GObject *object) +{ + GdGDataGoaAuthorizerPrivate *priv; + GType service_type; + GList *domains; + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (gd_gdata_goa_authorizer_parent_class)-> + constructed (object); + + priv = GD_GDATA_GOA_AUTHORIZER_GET_PRIVATE (object); + + /* XXX We would need to generalize this to make the class + * reusable for other service types, probably by adding + * a "service-type" constructor property. */ + service_type = GDATA_TYPE_DOCUMENTS_SERVICE; + domains = gdata_service_get_authorization_domains (service_type); + + while (domains != NULL) { + g_hash_table_insert ( + priv->authorization_domains, + g_object_ref (domains->data), + domains->data); + domains = g_list_delete_link (domains, domains); + } +} + +static void +gdata_goa_authorizer_process_request (GDataAuthorizer *authorizer, + GDataAuthorizationDomain *domain, + SoupMessage *message) +{ + GdGDataGoaAuthorizerPrivate *priv; + + priv = GD_GDATA_GOA_AUTHORIZER_GET_PRIVATE (authorizer); + + g_mutex_lock (&priv->mutex); + + if (gdata_goa_authorizer_is_authorized (authorizer, domain)) + gdata_goa_authorizer_add_authorization (authorizer, message); + + g_mutex_unlock (&priv->mutex); +} + +static gboolean +gdata_goa_authorizer_is_authorized_for_domain (GDataAuthorizer *authorizer, + GDataAuthorizationDomain *domain) +{ + GdGDataGoaAuthorizerPrivate *priv; + gboolean authorized; + + priv = GD_GDATA_GOA_AUTHORIZER_GET_PRIVATE (authorizer); + + g_mutex_lock (&priv->mutex); + + authorized = gdata_goa_authorizer_is_authorized (authorizer, domain); + + g_mutex_unlock (&priv->mutex); + + return authorized; +} + +static gboolean +gdata_goa_authorizer_refresh_authorization (GDataAuthorizer *authorizer, + GCancellable *cancellable, + GError **error) +{ + GdGDataGoaAuthorizerPrivate *priv; + GoaOAuthBased *goa_oauth_based; + GoaAccount *goa_account; + gboolean success = TRUE; + + priv = GD_GDATA_GOA_AUTHORIZER_GET_PRIVATE (authorizer); + + g_mutex_lock (&priv->mutex); + + g_free (priv->access_token); + priv->access_token = NULL; + + g_free (priv->access_token_secret); + priv->access_token_secret = NULL; + + goa_account = goa_object_get_account (priv->goa_object); + goa_oauth_based = goa_object_get_oauth_based (priv->goa_object); + + success &= goa_account_call_ensure_credentials_sync ( + goa_account, NULL, cancellable, error); + + success &= goa_oauth_based_call_get_access_token_sync ( + goa_oauth_based, &priv->access_token, + &priv->access_token_secret, NULL, cancellable, error); + + g_object_unref (goa_account); + g_object_unref (goa_oauth_based); + + g_mutex_unlock (&priv->mutex); + + return success; +} + +static void +gd_gdata_goa_authorizer_class_init (GdGDataGoaAuthorizerClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (GdGDataGoaAuthorizerPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = gdata_goa_authorizer_set_property; + object_class->get_property = gdata_goa_authorizer_get_property; + object_class->dispose = gdata_goa_authorizer_dispose; + object_class->finalize = gdata_goa_authorizer_finalize; + object_class->constructed = gdata_goa_authorizer_constructed; + + g_object_class_install_property ( + object_class, + PROP_GOA_OBJECT, + g_param_spec_object ( + "goa-object", + "GoaObject", + "The GOA account to authenticate", + GOA_TYPE_OBJECT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +gd_gdata_goa_authorizer_interface_init (GDataAuthorizerInterface *interface) +{ + interface->process_request = + gdata_goa_authorizer_process_request; + interface->is_authorized_for_domain = + gdata_goa_authorizer_is_authorized_for_domain; + interface->refresh_authorization = + gdata_goa_authorizer_refresh_authorization; +} + +static void +gd_gdata_goa_authorizer_init (GdGDataGoaAuthorizer *authorizer) +{ + GHashTable *authorization_domains; + + authorization_domains = g_hash_table_new_full ( + (GHashFunc) g_direct_hash, + (GEqualFunc) g_direct_equal, + (GDestroyNotify) g_object_unref, + (GDestroyNotify) NULL); + + authorizer->priv = GD_GDATA_GOA_AUTHORIZER_GET_PRIVATE (authorizer); + g_mutex_init (&authorizer->priv->mutex); + authorizer->priv->authorization_domains = authorization_domains; +} + +/** + * gd_gdata_goa_authorizer_new: + * @goa_object: + * + * Returns: (transfer full): + */ +GdGDataGoaAuthorizer * +gd_gdata_goa_authorizer_new (GoaObject *goa_object) +{ + g_return_val_if_fail (GOA_IS_OBJECT (goa_object), NULL); + + return g_object_new ( + GD_TYPE_GDATA_GOA_AUTHORIZER, + "goa-object", goa_object, NULL); +} + +/** + * gd_gdata_goa_authorizer_get_goa_object: + * @authorizer: + * + * Returns: (transfer none): + */ +GoaObject * +gd_gdata_goa_authorizer_get_goa_object (GdGDataGoaAuthorizer *authorizer) +{ + g_return_val_if_fail (GD_IS_GDATA_GOA_AUTHORIZER (authorizer), NULL); + + return authorizer->priv->goa_object; +} diff --git a/src/gd-gdata-goa-authorizer.h b/src/gd-gdata-goa-authorizer.h new file mode 100644 index 0000000..26c8faa --- /dev/null +++ b/src/gd-gdata-goa-authorizer.h @@ -0,0 +1,66 @@ +/* + * e-gdata-goa-authorizer.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + */ + +#ifndef GD_GDATA_GOA_AUTHORIZER_H +#define GD_GDATA_GOA_AUTHORIZER_H + +#include <gdata/gdata.h> +#include <goa/goa.h> + +/* Standard GObject macros */ +#define GD_TYPE_GDATA_GOA_AUTHORIZER \ + (gd_gdata_goa_authorizer_get_type ()) +#define GD_GDATA_GOA_AUTHORIZER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), GD_TYPE_GDATA_GOA_AUTHORIZER, GdGDataGoaAuthorizer)) +#define GD_GDATA_GOA_AUTHORIZER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), GD_TYPE_GDATA_GOA_AUTHORIZER, GdGDataGoaAuthorizerClass)) +#define GD_IS_GDATA_GOA_AUTHORIZER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), GD_TYPE_GDATA_GOA_AUTHORIZER)) +#define GD_IS_GDATA_GOA_AUTHORIZER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), GD_TYPE_GDATA_GOA_AUTHORIZER)) +#define GD_GDATA_GOA_AUTHORIZER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), GD_TYPE_GDATA_GOA_AUTHORIZER, GdGDataGoaAuthorizerClass)) + +G_BEGIN_DECLS + +typedef struct _GdGDataGoaAuthorizer GdGDataGoaAuthorizer; +typedef struct _GdGDataGoaAuthorizerClass GdGDataGoaAuthorizerClass; +typedef struct _GdGDataGoaAuthorizerPrivate GdGDataGoaAuthorizerPrivate; + +struct _GdGDataGoaAuthorizer { + GObject parent; + GdGDataGoaAuthorizerPrivate *priv; +}; + +struct _GdGDataGoaAuthorizerClass { + GObjectClass parent_class; +}; + +GType gd_gdata_goa_authorizer_get_type (void); +GdGDataGoaAuthorizer * + gd_gdata_goa_authorizer_new + (GoaObject *goa_object); +GoaObject * gd_gdata_goa_authorizer_get_goa_object + (GdGDataGoaAuthorizer *authorizer); + +#endif /* GD_GDATA_GOA_AUTHORIZER_H */ diff --git a/src/google-authorizer.vapi b/src/google-authorizer.vapi new file mode 100644 index 0000000..487cd6d --- /dev/null +++ b/src/google-authorizer.vapi @@ -0,0 +1,5 @@ +[CCode (cprefix = "GdGDataGoaAuthorizer", lower_case_cprefix = "gd_gdata_goa_authorizer_", cheader_filename = "gd-gdata-goa-authorizer.h")] +class GoogleAuthorizer { + public GoogleAuthorizer (GoaObject *goa_object); + public GoaObject* get_goa_object (); +} diff --git a/src/google-provider.vala b/src/google-provider.vala new file mode 100644 index 0000000..c4f67ac --- /dev/null +++ b/src/google-provider.vala @@ -0,0 +1,68 @@ +/* + * Zeitgeist + * + * Copyright (C) 2011-2012 Collabora Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authored by Siegfried-A. Gevatter <siegfried.gevatter@collabora.co.uk> + * + */ + +using Zeitgeist; + +public class GoogleProvider : DataProvider +{ + public GoogleProvider (DataHub datahub) throws GLib.Error + { + GLib.Object (unique_id: "com.zeitgeist-project,datahub,google", + name: "Google Data-Source", + description: "Logs events from Google services", + datahub: datahub); + } + + // if vala didn't have bug in construct-only properties, the properties + // would be construct-only + public override string unique_id { get; construct set; } + public override string name { get; construct set; } + public override string description { get; construct set; } + + public override DataHub datahub { get; construct set; } + public override bool enabled { get; set; default = true; } + public override bool register { get; construct set; default = true; } + + private GoaClient goa_client; + + construct + { + last_timestamp = 0; + } + + public override void start () + { + if (goa_client == null) + { + goa_client = new GoaClient.sync(); + foreach (GoaObject account in goa_client.get_accounts ()) + { + warning ("HI! FOUND ACCOUNT!"); + } + } + } + + public override void stop () + { + } + +} diff --git a/src/zeitgeist-datahub.vala b/src/zeitgeist-datahub.vala index a336cbb..ed28fc9 100644 --- a/src/zeitgeist-datahub.vala +++ b/src/zeitgeist-datahub.vala @@ -112,6 +112,7 @@ public class DataHub : Object, DataHubService providers.prepend (new RecentManagerGtk (this)); providers.prepend (new RecentDocumentsKDE (this)); providers.prepend (new TelepathyObserver (this)); + providers.prepend (new GoogleProvider (this)); if (Config.DOWNLOADS_MONITOR_ENABLED) providers.prepend (new DownloadsDirectoryMonitor (this)); |