diff options
Diffstat (limited to 'src/libtracker-miner/tracker-miner-online.c')
-rw-r--r-- | src/libtracker-miner/tracker-miner-online.c | 379 |
1 files changed, 379 insertions, 0 deletions
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 <abustany@gnome.org> + * Copyright (C) 2014, Carlos Garnacho <carlosg@gnome.org> + * + * 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 <libnm-glib/nm-client.h> +#include <glib/gi18n.h> + +#ifndef NM_CHECK_VERSION +#define NM_CHECK_VERSION(x,y,z) (0) +#endif + +#include <libnm-glib/nm-device-ethernet.h> +#include <libnm-glib/nm-device-wifi.h> +#if (NM_CHECK_VERSION (0,8,992)) +#include <libnm-glib/nm-device-modem.h> +#include <libnm-glib/nm-device-wimax.h> +#else +#include <libnm-glib/nm-gsm-device.h> +#include <libnm-glib/nm-cdma-device.h> +#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 + * <literal>connected</literal> 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; +} |