From 0c2e04e263a7ada1e834ce1fe6a41cc2383d76ff Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Wed, 29 Jan 2014 00:03:47 +0100 Subject: libtracker-miner: Add TrackerMinerOnline This TrackerMiner is a simpler replacement for TrackerMinerWeb that doesn't get into credentials handling. It handles network state, emitting ::connected or ::disconnected on the way, and ensuring the miner is paused/resumed as necessary when suitable networks come and go, implementations of this miner can control this behavior through the return value in the ::connected signal. --- .../libtracker-miner/libtracker-miner-docs.sgml | 1 + .../libtracker-miner/libtracker-miner-sections.txt | 16 + src/libtracker-miner/Makefile.am | 5 +- src/libtracker-miner/tracker-miner-enums.h | 28 ++ src/libtracker-miner/tracker-miner-online.c | 379 +++++++++++++++++++++ src/libtracker-miner/tracker-miner-online.h | 70 ++++ src/libtracker-miner/tracker-miner.h | 1 + src/libtracker-miner/tracker-miner.vapi | 14 + 8 files changed, 513 insertions(+), 1 deletion(-) create mode 100644 src/libtracker-miner/tracker-miner-online.c create mode 100644 src/libtracker-miner/tracker-miner-online.h diff --git a/docs/reference/libtracker-miner/libtracker-miner-docs.sgml b/docs/reference/libtracker-miner/libtracker-miner-docs.sgml index 99b089c55..769dbb1f5 100644 --- a/docs/reference/libtracker-miner/libtracker-miner-docs.sgml +++ b/docs/reference/libtracker-miner/libtracker-miner-docs.sgml @@ -32,6 +32,7 @@ Base abstract miner classes + diff --git a/docs/reference/libtracker-miner/libtracker-miner-sections.txt b/docs/reference/libtracker-miner/libtracker-miner-sections.txt index 41c7f500e..f7b3b1c92 100644 --- a/docs/reference/libtracker-miner/libtracker-miner-sections.txt +++ b/docs/reference/libtracker-miner/libtracker-miner-sections.txt @@ -193,6 +193,22 @@ TRACKER_TYPE_PASSWORD_PROVIDER tracker_password_provider_get_type +
+tracker-miner-online +TrackerMinerOnline</FILE> +TrackerMinerOnline +TrackerMinerOnlineClass +tracker_miner_online_get_type +tracker_miner_online_get_network_type +<SUBSECTION Standard> +TRACKER_MINER_ONLINE +TRACKER_MINER_ONLINE_CLASS +TRACKER_MINER_ONLINE_GET_CLASS +TRACKER_IS_MINER_ONLINE +TRACKER_IS_MINER_ONLINE_CLASS +TRACKER_TYPE_MINER_ONLINE +</SECTION> + <SECTION> <FILE>tracker-decorator</FILE> <TITLE>TrackerDecorator diff --git a/src/libtracker-miner/Makefile.am b/src/libtracker-miner/Makefile.am index 69037ab52..ef53fd1bf 100644 --- a/src/libtracker-miner/Makefile.am +++ b/src/libtracker-miner/Makefile.am @@ -65,6 +65,8 @@ miner_sources = \ tracker-miner-enum-types.h \ tracker-miner-object.c \ tracker-miner-object.h \ + tracker-miner-online.c \ + tracker-miner-online.h \ tracker-miner-fs.c \ tracker-miner-fs.h \ tracker-miner-web.c \ @@ -92,6 +94,7 @@ libtracker_minerinclude_HEADERS = \ tracker-miner-enums.h \ tracker-miner-enum-types.h \ tracker-miner-object.h \ + tracker-miner-online.h \ tracker-miner-fs.h \ tracker-miner-web.h \ tracker-network-provider.h \ @@ -103,7 +106,7 @@ if !ENABLE_GCOV # Using enable_gcov instead of have_unit_test because when doing a release # we disable gcov but NOT the unit tests libtracker_miner_@TRACKER_API_VERSION@_la_LDFLAGS += \ - -export-symbols-regex '^tracker_(miner|password_provider|network_provider|indexing_tree|file_system|file_notifier|directory_flags|filter_type|filter_policy|decorator)_.*' + -export-symbols-regex '^tracker_(miner|password_provider|network_provider|indexing_tree|file_system|file_notifier|directory_flags|filter_type|filter_policy|network_type|decorator)_.*' endif libtracker_miner_@TRACKER_API_VERSION@_la_LIBADD = \ diff --git a/src/libtracker-miner/tracker-miner-enums.h b/src/libtracker-miner/tracker-miner-enums.h index ecfaf3527..941b10aaf 100644 --- a/src/libtracker-miner/tracker-miner-enums.h +++ b/src/libtracker-miner/tracker-miner-enums.h @@ -80,6 +80,34 @@ typedef enum { TRACKER_FILTER_POLICY_ACCEPT } TrackerFilterPolicy; +/** + * TrackerNetworkType: + * @TRACKER_NETWORK_TYPE_NONE: Network is disconnected + * @TRACKER_NETWORK_TYPE_UNKNOWN: Network status is unknown + * @TRACKER_NETWORK_TYPE_GPRS: Network is connected over a GPRS + * connection + * @TRACKER_NETWORK_TYPE_EDGE: Network is connected over an EDGE + * connection + * @TRACKER_NETWORK_TYPE_3G: Network is connected over a 3G or + * faster (HSDPA, UMTS, ...) connection + * @TRACKER_NETWORK_TYPE_LAN: Network is connected over a local + * network connection. This can be ethernet, wifi, etc. + * + * Enumerates the different types of connections that the device might + * use when connected to internet. Note that not all providers might + * provide this information. + * + * Since: 0.18 + **/ +typedef enum { + TRACKER_NETWORK_TYPE_NONE, + TRACKER_NETWORK_TYPE_UNKNOWN, + TRACKER_NETWORK_TYPE_GPRS, + TRACKER_NETWORK_TYPE_EDGE, + TRACKER_NETWORK_TYPE_3G, + TRACKER_NETWORK_TYPE_LAN +} TrackerNetworkType; + G_END_DECLS #endif /* __TRACKER_MINER_ENUMS_H__ */ diff --git a/src/libtracker-miner/tracker-miner-online.c b/src/libtracker-miner/tracker-miner-online.c new file mode 100644 index 000000000..f84c9237f --- /dev/null +++ b/src/libtracker-miner/tracker-miner-online.c @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2009-2014, Adrien Bustany + * Copyright (C) 2014, Carlos Garnacho + * + * This library 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.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "tracker-miner-online.h" +#include "tracker-miner-enum-types.h" + +#include +#include + +#ifndef NM_CHECK_VERSION +#define NM_CHECK_VERSION(x,y,z) (0) +#endif + +#include +#include +#if (NM_CHECK_VERSION (0,8,992)) +#include +#include +#else +#include +#include +#endif + +/** + * SECTION:tracker-miner-online + * @short_description: Abstract base class for miners connecting to + * online resources + * @include: libtracker-miner/tracker-miner.h + * + * #TrackerMinerOnline is an abstract base class for miners retrieving data + * from online resources. It's a very thin layer above #TrackerMiner that + * additionally handles network connection status. + * + * #TrackerMinerOnline implementations can implement the + * connected vmethod in order to tell the miner whether + * a connection is valid to retrieve data or not. The miner data extraction + * still must be dictated through the #TrackerMiner vmethods. + **/ + +typedef struct _TrackerMinerOnlinePrivate TrackerMinerOnlinePrivate; + +struct _TrackerMinerOnlinePrivate { +#ifdef HAVE_NETWORK_MANAGER + NMClient *client; +#endif + TrackerNetworkType network_type; + gint pause_id; +}; + +enum { + PROP_NETWORK_TYPE = 1 +}; + +enum { + CONNECTED, + DISCONNECTED, + N_SIGNALS +}; + +static void miner_online_initable_iface_init (GInitableIface *iface); + +static GInitableIface* miner_online_initable_parent_iface; +static guint signals[N_SIGNALS] = { 0 }; + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (TrackerMinerOnline, tracker_miner_online, TRACKER_TYPE_MINER, + G_ADD_PRIVATE (TrackerMinerOnline) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + miner_online_initable_iface_init)); + +static void +miner_online_finalize (GObject *object) +{ + TrackerMinerOnlinePrivate *priv; + TrackerMinerOnline *miner; + + miner = TRACKER_MINER_ONLINE (object); + priv = tracker_miner_online_get_instance_private (miner); + + if (priv->client) + g_object_unref (priv->client); + + G_OBJECT_CLASS (tracker_miner_online_parent_class)->finalize (object); +} + +static void +miner_online_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (param_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +miner_online_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + TrackerMinerOnlinePrivate *priv; + TrackerMinerOnline *miner; + + miner = TRACKER_MINER_ONLINE (object); + priv = tracker_miner_online_get_instance_private (miner); + + switch (param_id) { + case PROP_NETWORK_TYPE: + g_value_set_enum (value, priv->network_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +tracker_miner_online_class_init (TrackerMinerOnlineClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = miner_online_finalize; + object_class->set_property = miner_online_set_property; + object_class->get_property = miner_online_get_property; + + g_object_class_install_property (object_class, + PROP_NETWORK_TYPE, + g_param_spec_enum ("network-type", + "Network type", + "Network type for the current connection", + TRACKER_TYPE_NETWORK_TYPE, + TRACKER_NETWORK_TYPE_NONE, + G_PARAM_READABLE)); + signals[CONNECTED] = + g_signal_new ("connected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (TrackerMinerOnlineClass, connected), + NULL, NULL, NULL, + G_TYPE_BOOLEAN, 1, TRACKER_TYPE_NETWORK_TYPE); + signals[DISCONNECTED] = + g_signal_new ("disconnected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (TrackerMinerOnlineClass, connected), + NULL, NULL, NULL, + G_TYPE_NONE, 0); +} + +static void +tracker_miner_online_init (TrackerMinerOnline *miner) +{ + TrackerMinerOnlinePrivate *priv; + + priv = tracker_miner_online_get_instance_private (miner); + priv->network_type = TRACKER_NETWORK_TYPE_NONE; +} + +#ifdef HAVE_NETWORK_MANAGER +/* + * Returns the first NMActiveConnection with the "default" property set, or + * NULL if none is found. + */ +static NMActiveConnection* +find_default_active_connection (NMClient *client) +{ + NMActiveConnection *active_connection = NULL; + const GPtrArray *active_connections; + gint i; + + active_connections = nm_client_get_active_connections (client); + + for (i = 0; i < active_connections->len; i++) { + active_connection = g_ptr_array_index (active_connections, i); + + if (nm_active_connection_get_default (active_connection)) { + break; + } + } + + return active_connection; +} + +static TrackerNetworkType +_nm_client_get_network_type (NMClient *nm_client) +{ + NMActiveConnection *default_active_connection; + const GPtrArray *devices; + NMDevice *device; + + if (!nm_client_get_manager_running (nm_client)) { + return TRACKER_NETWORK_TYPE_UNKNOWN; + } + + switch (nm_client_get_state (nm_client)) { + case NM_STATE_UNKNOWN: + return TRACKER_NETWORK_TYPE_UNKNOWN; + case NM_STATE_CONNECTED: + break; + default: + return TRACKER_NETWORK_TYPE_NONE; + } + + default_active_connection = find_default_active_connection (nm_client); + + if (!default_active_connection) { + return TRACKER_NETWORK_TYPE_NONE; + } + + switch (nm_active_connection_get_state (default_active_connection)) { + case NM_ACTIVE_CONNECTION_STATE_UNKNOWN: + return TRACKER_NETWORK_TYPE_UNKNOWN; + case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: + break; + default: + return TRACKER_NETWORK_TYPE_NONE; + } + + devices = nm_active_connection_get_devices (default_active_connection); + + if (!devices->len) { + return TRACKER_NETWORK_TYPE_NONE; + } + + /* Pick the first device, I don't know when there are more than one */ + device = g_ptr_array_index (devices, 0); + + switch (nm_device_get_state (device)) { + case NM_DEVICE_STATE_UNKNOWN: + return TRACKER_NETWORK_TYPE_UNKNOWN; + break; + case NM_DEVICE_STATE_ACTIVATED: + break; + default: + return TRACKER_NETWORK_TYPE_NONE; + } + + if (NM_IS_DEVICE_ETHERNET (device) || NM_IS_DEVICE_WIFI (device)) { + return TRACKER_NETWORK_TYPE_LAN; + } + +#if (NM_CHECK_VERSION (0,8,992)) + if (NM_IS_DEVICE_MODEM (device) || NM_IS_DEVICE_WIMAX (device)) { + return TRACKER_NETWORK_TYPE_3G; + } +#else + if (NM_IS_GSM_DEVICE (device) || NM_IS_CDMA_DEVICE (device)) { + return TRACKER_NETWORK_TYPE_3G; + } +#endif + + /* We know the device is activated, but we don't know the type of device */ + return TRACKER_NETWORK_TYPE_UNKNOWN; +} + +static void +_tracker_miner_online_set_network_type (TrackerMinerOnline *miner, + TrackerNetworkType type) +{ + TrackerMinerOnlinePrivate *priv; + gboolean cont = FALSE; + GError *error = NULL; + + priv = tracker_miner_online_get_instance_private (miner); + + if (type == priv->network_type) { + return; + } + + priv->network_type = type; + + if (type != TRACKER_NETWORK_TYPE_NONE) { + g_signal_emit (miner, signals[CONNECTED], 0, type, &cont); + } else { + g_signal_emit (miner, signals[DISCONNECTED], 0); + } + + if (cont && priv->pause_id) + tracker_miner_resume (TRACKER_MINER (miner), + priv->pause_id, &error); + else if (!cont && !priv->pause_id) { + const gchar *msg; + + msg = (type == TRACKER_NETWORK_TYPE_NONE) ? + _("No network connection") : + _("Indexing not recommended on this network connection"); + + priv->pause_id = + tracker_miner_pause (TRACKER_MINER (miner), + msg, &error); + } + + if (error) { + g_warning ("There was an error after getting network type %d: %s", + type, error->message); + g_error_free (error); + } +} + +static void +_nm_client_state_notify_cb (GObject *object, + GParamSpec *pspec, + TrackerMinerOnline *miner) +{ + TrackerMinerOnlinePrivate *priv; + TrackerNetworkType type; + + priv = tracker_miner_online_get_instance_private (miner); + type = _nm_client_get_network_type (priv->client); + _tracker_miner_online_set_network_type (miner, type); +} +#endif /* HAVE_NETWORK_MANAGER */ + +static gboolean +miner_online_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + TrackerMinerOnlinePrivate *priv; + TrackerNetworkType network_type; + TrackerMinerOnline *miner; + + miner = TRACKER_MINER_ONLINE (initable); + priv = tracker_miner_online_get_instance_private (miner); + + if (!miner_online_initable_parent_iface->init (initable, + cancellable, error)) { + return FALSE; + } + +#ifdef HAVE_NETWORK_MANAGER + priv->client = nm_client_new (); + g_signal_connect (priv->client, "notify::state", + G_CALLBACK (_nm_client_state_notify_cb), miner); + network_type = _nm_client_get_network_type (priv->client); + _tracker_miner_online_set_network_type (miner, network_type); +#endif + + return TRUE; +} + +static void +miner_online_initable_iface_init (GInitableIface *iface) +{ + miner_online_initable_parent_iface = g_type_interface_peek_parent (iface); + iface->init = miner_online_initable_init; +} + +TrackerNetworkType +tracker_miner_online_get_network_type (TrackerMinerOnline *miner) +{ + TrackerMinerOnlinePrivate *priv; + + priv = tracker_miner_online_get_instance_private (miner); + + return priv->network_type; +} diff --git a/src/libtracker-miner/tracker-miner-online.h b/src/libtracker-miner/tracker-miner-online.h new file mode 100644 index 000000000..91c5b3205 --- /dev/null +++ b/src/libtracker-miner/tracker-miner-online.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009, Adrien Bustany + * + * This library 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.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __LIBTRACKER_MINER_ONLINE_H__ +#define __LIBTRACKER_MINER_ONLINE_H__ + +#if !defined (__LIBTRACKER_MINER_H_INSIDE__) && !defined (TRACKER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +#define TRACKER_TYPE_MINER_ONLINE (tracker_miner_online_get_type()) +#define TRACKER_MINER_ONLINE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MINER_ONLINE, TrackerMinerOnline)) +#define TRACKER_MINER_ONLINE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_MINER_ONLINE, TrackerMinerOnlineClass)) +#define TRACKER_IS_MINER_ONLINE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_MINER_ONLINE)) +#define TRACKER_IS_MINER_ONLINE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_MINER_ONLINE)) +#define TRACKER_MINER_ONLINE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_MINER_ONLINE, TrackerMinerOnlineClass)) + +G_BEGIN_DECLS + +typedef struct _TrackerMinerOnline TrackerMinerOnline; +typedef struct _TrackerMinerOnlineClass TrackerMinerOnlineClass; + +struct _TrackerMinerOnline { + TrackerMiner parent_instance; +}; + +/** + * TrackerMinerOnlineClass: + * @parent_class: parent object class + * @connected: called when there is a network connection, or a new + * default route, returning #TRUE starts/resumes indexing. + * @disconnected: called when there is no network connection. + * + * Since: 0.18. + **/ +struct _TrackerMinerOnlineClass { + TrackerMinerClass parent_class; + + /* vmethods */ + gboolean (* connected) (TrackerMinerOnline *miner, + TrackerNetworkType network); + void (* disconnected) (TrackerMinerOnline *miner); +}; + +GType tracker_miner_online_get_type (void) G_GNUC_CONST; + +TrackerNetworkType tracker_miner_online_get_network_type (TrackerMinerOnline *miner); + +G_END_DECLS + +#endif /* __LIBTRACKER_MINER_ONLINE_H__ */ diff --git a/src/libtracker-miner/tracker-miner.h b/src/libtracker-miner/tracker-miner.h index 208a3db54..cd6acc144 100644 --- a/src/libtracker-miner/tracker-miner.h +++ b/src/libtracker-miner/tracker-miner.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/src/libtracker-miner/tracker-miner.vapi b/src/libtracker-miner/tracker-miner.vapi index b2ab28785..163e4e7fc 100644 --- a/src/libtracker-miner/tracker-miner.vapi +++ b/src/libtracker-miner/tracker-miner.vapi @@ -63,6 +63,20 @@ namespace Tracker { public signal void finished (double elapsed, uint directories_found, uint directories_ignored, uint files_found, uint files_ignored); } [CCode (cheader_filename = "libtracker-miner/tracker-miner.h")] + public class MinerOnline : Tracker.Miner, GLib.Initable { + public virtual bool connected (Tracker.NetworkType network_type); + public virtual void disconnected (); + } + [CCode (cprefix = "TRACKER_NETWORK_TYPE_", cheader_filename = "libtracker-miner/tracker-miner.h")] + public enum NetworkType { + NONE, + UNKNOWN, + GPRS, + EDGE, + 3G, + LAN + } + [CCode (cheader_filename = "libtracker-miner/tracker-miner.h")] public class MinerWeb : Tracker.Miner, GLib.Initable { [CCode (has_construct_function = false)] public MinerWeb (); -- cgit v1.2.1