gnome-control-center/panels/network/net-device-wifi.c
2019-09-17 12:15:11 +00:00

1622 lines
61 KiB
C

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU General Public License Version 2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#define HANDY_USE_UNSTABLE_API
#include <handy.h>
#include <glib-object.h>
#include <glib/gi18n.h>
#include <netinet/ether.h>
#include <NetworkManager.h>
#include <polkit/polkit.h>
#include "cc-wifi-hotspot-dialog.h"
#include "list-box-helper.h"
#include "hostname-helper.h"
#include "network-dialogs.h"
#include "panel-common.h"
#include "connection-editor/net-connection-editor.h"
#include "net-device-wifi.h"
#include "cc-wifi-connection-list.h"
#include "cc-wifi-connection-row.h"
#define PERIODIC_WIFI_SCAN_TIMEOUT 15
static void nm_device_wifi_refresh_ui (NetDeviceWifi *device_wifi);
static void show_wifi_list (NetDeviceWifi *device_wifi);
static void show_hotspot_ui (NetDeviceWifi *device_wifi);
static void ap_activated (GtkListBox *list, GtkListBoxRow *row, NetDeviceWifi *device_wifi);
static gint ap_sort (gconstpointer a, gconstpointer b, gpointer data);
static void show_details_for_row (NetDeviceWifi *device_wifi, CcWifiConnectionRow *row, CcWifiConnectionList *list );
struct _NetDeviceWifi
{
NetDevice parent;
GtkBuilder *builder;
GtkWidget *details_dialog;
GtkSwitch *hotspot_switch;
gboolean updating_device;
gchar *selected_ssid_title;
gchar *selected_connection_id;
gchar *selected_ap_id;
CcWifiHotspotDialog *hotspot_dialog;
gint64 last_scan;
gboolean scanning;
guint monitor_scanning_id;
guint scan_id;
GCancellable *cancellable;
};
enum {
PROP_0,
PROP_SCANNING,
PROP_LAST,
};
G_DEFINE_TYPE (NetDeviceWifi, net_device_wifi, NET_TYPE_DEVICE)
GtkWidget *
net_device_wifi_get_header_widget (NetDeviceWifi *device_wifi)
{
return GTK_WIDGET (gtk_builder_get_object (device_wifi->builder, "header_box"));
}
GtkWidget *
net_device_wifi_get_title_widget (NetDeviceWifi *device_wifi)
{
return GTK_WIDGET (gtk_builder_get_object (device_wifi->builder, "center_box"));
}
static GtkWidget *
device_wifi_proxy_add_to_stack (NetObject *object,
GtkStack *stack,
GtkSizeGroup *heading_size_group)
{
NMDevice *nmdevice;
GtkWidget *widget;
NetDeviceWifi *device_wifi = NET_DEVICE_WIFI (object);
nmdevice = net_device_get_nm_device (NET_DEVICE (object));
/* add widgets to size group */
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder,
"heading_ipv4"));
gtk_size_group_add_widget (heading_size_group, widget);
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder,
"notebook_view"));
gtk_stack_add_titled (stack, widget,
net_object_get_id (object),
nm_device_get_description (nmdevice));
return widget;
}
static gchar *
get_ap_security_string (NMAccessPoint *ap)
{
NM80211ApSecurityFlags wpa_flags, rsn_flags;
NM80211ApFlags flags;
GString *str;
flags = nm_access_point_get_flags (ap);
wpa_flags = nm_access_point_get_wpa_flags (ap);
rsn_flags = nm_access_point_get_rsn_flags (ap);
str = g_string_new ("");
if ((flags & NM_802_11_AP_FLAGS_PRIVACY) &&
(wpa_flags == NM_802_11_AP_SEC_NONE) &&
(rsn_flags == NM_802_11_AP_SEC_NONE)) {
/* TRANSLATORS: this WEP WiFi security */
g_string_append_printf (str, "%s, ", _("WEP"));
}
if (wpa_flags != NM_802_11_AP_SEC_NONE) {
/* TRANSLATORS: this WPA WiFi security */
g_string_append_printf (str, "%s, ", _("WPA"));
}
if (rsn_flags != NM_802_11_AP_SEC_NONE) {
/* TRANSLATORS: this WPA WiFi security */
g_string_append_printf (str, "%s, ", _("WPA2"));
}
if ((wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) ||
(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
/* TRANSLATORS: this Enterprise WiFi security */
g_string_append_printf (str, "%s, ", _("Enterprise"));
}
if (str->len > 0)
g_string_set_size (str, str->len - 2);
else {
g_string_append (str, C_("Wifi security", "None"));
}
return g_string_free (str, FALSE);
}
static void
disable_scan_timeout (NetDeviceWifi *device_wifi)
{
g_debug ("Disabling periodic Wi-Fi scan");
if (device_wifi->monitor_scanning_id > 0) {
g_source_remove (device_wifi->monitor_scanning_id);
device_wifi->monitor_scanning_id = 0;
}
if (device_wifi->scan_id > 0) {
g_source_remove (device_wifi->scan_id);
device_wifi->scan_id = 0;
}
}
static void
wireless_enabled_toggled (NMClient *client,
GParamSpec *pspec,
NetDeviceWifi *device_wifi)
{
gboolean enabled;
GtkSwitch *sw;
NMDevice *device;
device = net_device_get_nm_device (NET_DEVICE (device_wifi));
if (nm_device_get_device_type (device) != NM_DEVICE_TYPE_WIFI)
return;
enabled = nm_client_wireless_get_enabled (client);
sw = GTK_SWITCH (gtk_builder_get_object (device_wifi->builder,
"device_off_switch"));
device_wifi->updating_device = TRUE;
gtk_switch_set_active (sw, enabled);
if (!enabled)
disable_scan_timeout (device_wifi);
device_wifi->updating_device = FALSE;
}
static NMConnection *
find_connection_for_device (NetDeviceWifi *device_wifi,
NMDevice *device)
{
g_autoptr(NetDevice) tmp = NULL;
NMConnection *connection;
NMClient *client;
client = net_object_get_client (NET_OBJECT (device_wifi));
tmp = g_object_new (NET_TYPE_DEVICE,
"client", client,
"nm-device", device,
NULL);
connection = net_device_get_find_connection (tmp);
return connection;
}
static gboolean
connection_is_shared (NMConnection *c)
{
NMSettingIPConfig *s_ip4;
s_ip4 = nm_connection_get_setting_ip4_config (c);
if (g_strcmp0 (nm_setting_ip_config_get_method (s_ip4),
NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0) {
return FALSE;
}
return TRUE;
}
static gboolean
device_is_hotspot (NetDeviceWifi *device_wifi)
{
NMConnection *c;
NMDevice *device;
device = net_device_get_nm_device (NET_DEVICE (device_wifi));
if (nm_device_get_active_connection (device) == NULL)
return FALSE;
c = find_connection_for_device (device_wifi, device);
if (c == NULL)
return FALSE;
return connection_is_shared (c);
}
static GBytes *
device_get_hotspot_ssid (NetDeviceWifi *device_wifi,
NMDevice *device)
{
NMConnection *c;
NMSettingWireless *sw;
c = find_connection_for_device (device_wifi, device);
if (c == NULL)
return NULL;
sw = nm_connection_get_setting_wireless (c);
return nm_setting_wireless_get_ssid (sw);
}
static void
get_secrets_cb (GObject *source_object,
GAsyncResult *res,
gpointer data)
{
NetDeviceWifi *device_wifi = data;
GVariant *secrets;
g_autoptr(GError) error = NULL;
secrets = nm_remote_connection_get_secrets_finish (NM_REMOTE_CONNECTION (source_object), res, &error);
if (!secrets) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Could not get secrets: %s", error->message);
return;
}
nm_connection_update_secrets (NM_CONNECTION (source_object),
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
secrets, NULL);
nm_device_wifi_refresh_ui (device_wifi);
}
static void
device_get_hotspot_security_details (NetDeviceWifi *device_wifi,
NMDevice *device,
gchar **secret,
gchar **security)
{
NMConnection *c;
NMSettingWirelessSecurity *sws;
const gchar *key_mgmt;
const gchar *tmp_secret;
const gchar *tmp_security;
c = find_connection_for_device (device_wifi, device);
if (c == NULL)
return;
sws = nm_connection_get_setting_wireless_security (c);
if (sws == NULL)
return;
tmp_secret = NULL;
tmp_security = C_("Wifi security", "None");
/* Key management values:
* "none" = WEP
* "wpa-none" = WPAv1 Ad-Hoc mode (not supported in NM >= 0.9.4)
* "wpa-psk" = WPAv2 Ad-Hoc mode (eg IBSS RSN) and AP-mode WPA v1 and v2
*/
key_mgmt = nm_setting_wireless_security_get_key_mgmt (sws);
if (strcmp (key_mgmt, "none") == 0) {
tmp_secret = nm_setting_wireless_security_get_wep_key (sws, 0);
tmp_security = _("WEP");
}
else if (strcmp (key_mgmt, "wpa-none") == 0 ||
strcmp (key_mgmt, "wpa-psk") == 0) {
tmp_secret = nm_setting_wireless_security_get_psk (sws);
tmp_security = _("WPA");
} else {
g_warning ("unhandled security key-mgmt: %s", key_mgmt);
}
/* If we don't have secrets, request them from NM and bail.
* We'll refresh the UI when secrets arrive.
*/
if (tmp_secret == NULL) {
GCancellable *cancellable = net_object_get_cancellable (NET_OBJECT (device_wifi));
nm_remote_connection_get_secrets_async ((NMRemoteConnection*)c,
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
cancellable,
get_secrets_cb,
device_wifi);
return;
}
if (secret)
*secret = g_strdup (tmp_secret);
if (security)
*security = g_strdup (tmp_security);
}
static void
nm_device_wifi_refresh_hotspot (NetDeviceWifi *device_wifi)
{
GBytes *ssid;
g_autofree gchar *hotspot_secret = NULL;
g_autofree gchar *hotspot_security = NULL;
g_autofree gchar *hotspot_ssid = NULL;
NMDevice *nm_device;
/* refresh hotspot ui */
nm_device = net_device_get_nm_device (NET_DEVICE (device_wifi));
ssid = device_get_hotspot_ssid (device_wifi, nm_device);
if (ssid)
hotspot_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
device_get_hotspot_security_details (device_wifi,
nm_device,
&hotspot_secret,
&hotspot_security);
g_debug ("Refreshing hotspot labels to name: '%s', security key: '%s', security: '%s'",
hotspot_ssid, hotspot_secret, hotspot_security);
panel_set_device_widget_details (device_wifi->builder,
"hotspot_network_name",
hotspot_ssid);
panel_set_device_widget_details (device_wifi->builder,
"hotspot_security_key",
hotspot_secret);
panel_set_device_widget_details (device_wifi->builder,
"hotspot_security",
hotspot_security);
panel_set_device_widget_details (device_wifi->builder,
"hotspot_connected",
NULL);
}
static void
update_last_used (NetDeviceWifi *device_wifi, NMConnection *connection)
{
g_autofree gchar *last_used = NULL;
g_autoptr(GDateTime) now = NULL;
g_autoptr(GDateTime) then = NULL;
gint days;
GTimeSpan diff;
guint64 timestamp;
NMSettingConnection *s_con;
s_con = nm_connection_get_setting_connection (connection);
if (s_con == NULL)
goto out;
timestamp = nm_setting_connection_get_timestamp (s_con);
if (timestamp == 0) {
last_used = g_strdup (_("never"));
goto out;
}
/* calculate the amount of time that has elapsed */
now = g_date_time_new_now_utc ();
then = g_date_time_new_from_unix_utc (timestamp);
diff = g_date_time_difference (now, then);
days = diff / G_TIME_SPAN_DAY;
if (days == 0)
last_used = g_strdup (_("today"));
else if (days == 1)
last_used = g_strdup (_("yesterday"));
else
last_used = g_strdup_printf (ngettext ("%i day ago", "%i days ago", days), days);
out:
panel_set_device_widget_details (device_wifi->builder,
"last_used",
last_used);
}
static void
set_scanning (NetDeviceWifi *self,
gboolean scanning,
gint64 last_scan)
{
gboolean scanning_changed = self->scanning != scanning;
self->scanning = scanning;
self->last_scan = last_scan;
if (scanning_changed)
g_object_notify (G_OBJECT (self), "scanning");
}
static gboolean
update_scanning (gpointer user_data)
{
NetDeviceWifi *device_wifi = user_data;
NMDevice *nm_device;
gint64 last_scan;
nm_device = net_device_get_nm_device (NET_DEVICE (device_wifi));
last_scan = nm_device_wifi_get_last_scan (NM_DEVICE_WIFI (nm_device));
/* The last_scan property is updated after the device finished scanning,
* so notify about it and stop monitoring for changes.
*/
if (device_wifi->last_scan != last_scan) {
set_scanning (device_wifi, FALSE, last_scan);
device_wifi->monitor_scanning_id = 0;
return G_SOURCE_REMOVE;
}
return G_SOURCE_CONTINUE;
}
static gboolean
request_scan (gpointer user_data)
{
NetDeviceWifi *device_wifi = user_data;
NMDevice *nm_device;
g_debug ("Periodic Wi-Fi scan requested");
nm_device = net_device_get_nm_device (NET_DEVICE (device_wifi));
set_scanning (device_wifi, TRUE,
nm_device_wifi_get_last_scan (NM_DEVICE_WIFI (nm_device)));
if (device_wifi->monitor_scanning_id == 0) {
device_wifi->monitor_scanning_id = g_timeout_add (1500, update_scanning,
device_wifi);
}
nm_device_wifi_request_scan_async (NM_DEVICE_WIFI (nm_device),
device_wifi->cancellable, NULL, NULL);
return G_SOURCE_CONTINUE;
}
static void
nm_device_wifi_refresh_ui (NetDeviceWifi *device_wifi)
{
const gchar *str;
g_autofree gchar *speed_text = NULL;
g_autofree gchar *security_text = NULL;
gint strength = 0;
guint speed = 0;
NMAccessPoint *active_ap;
NMDevice *nm_device;
NMDeviceState state;
NMClient *client;
NMAccessPoint *ap;
NMConnection *connection;
GtkWidget *dialog;
if (device_is_hotspot (device_wifi)) {
nm_device_wifi_refresh_hotspot (device_wifi);
show_hotspot_ui (device_wifi);
disable_scan_timeout (device_wifi);
return;
}
client = net_object_get_client (NET_OBJECT (device_wifi));
if (device_wifi->scan_id == 0 &&
nm_client_wireless_get_enabled (client)) {
device_wifi->scan_id = g_timeout_add_seconds (PERIODIC_WIFI_SCAN_TIMEOUT,
request_scan, device_wifi);
request_scan (device_wifi);
}
dialog = device_wifi->details_dialog;
ap = g_object_get_data (G_OBJECT (dialog), "ap");
connection = g_object_get_data (G_OBJECT (dialog), "connection");
nm_device = net_device_get_nm_device (NET_DEVICE (device_wifi));
active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (nm_device));
state = nm_device_get_state (nm_device);
/* keep this in sync with the signal handler setup in cc_network_panel_init */
wireless_enabled_toggled (client, NULL, device_wifi);
if (ap != active_ap)
speed = 0;
else if (state != NM_DEVICE_STATE_UNAVAILABLE)
speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (nm_device));
speed /= 1000;
if (speed > 0) {
/* Translators: network device speed */
speed_text = g_strdup_printf (_("%d Mb/s"), speed);
}
panel_set_device_widget_details (device_wifi->builder,
"speed",
speed_text);
/* device MAC */
str = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (nm_device));
panel_set_device_widget_details (device_wifi->builder,
"mac",
str);
/* security */
if (ap == active_ap && active_ap != NULL)
security_text = get_ap_security_string (active_ap);
panel_set_device_widget_details (device_wifi->builder,
"security",
security_text);
/* signal strength */
if (ap != NULL)
strength = nm_access_point_get_strength (ap);
else
strength = 0;
if (strength <= 0)
str = NULL;
else if (strength < 20)
str = C_("Signal strength", "None");
else if (strength < 40)
str = C_("Signal strength", "Weak");
else if (strength < 50)
str = C_("Signal strength", "Ok");
else if (strength < 80)
str = C_("Signal strength", "Good");
else
str = C_("Signal strength", "Excellent");
panel_set_device_widget_details (device_wifi->builder,
"strength",
str);
/* device MAC */
if (ap != active_ap)
str = NULL;
else
str = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (nm_device));
panel_set_device_widget_details (device_wifi->builder, "mac", str);
/* set IP entries */
if (ap != active_ap)
panel_unset_device_widgets (device_wifi->builder);
else
panel_set_device_widgets (device_wifi->builder, nm_device);
if (ap != active_ap && connection)
update_last_used (device_wifi, connection);
else
panel_set_device_widget_details (device_wifi->builder, "last_used", NULL);
panel_set_device_status (device_wifi->builder, "heading_status", nm_device, NULL);
/* update list of APs */
show_wifi_list (device_wifi);
}
static void
device_wifi_refresh (NetObject *object)
{
NetDeviceWifi *device_wifi = NET_DEVICE_WIFI (object);
nm_device_wifi_refresh_ui (device_wifi);
}
static void
device_off_toggled (GtkSwitch *sw,
GParamSpec *pspec,
NetDeviceWifi *device_wifi)
{
NMClient *client;
gboolean active;
if (device_wifi->updating_device)
return;
client = net_object_get_client (NET_OBJECT (device_wifi));
active = gtk_switch_get_active (sw);
nm_client_wireless_set_enabled (client, active);
if (!active)
disable_scan_timeout (device_wifi);
}
static void
connect_to_hidden_network (NetDeviceWifi *device_wifi)
{
NMClient *client;
CcNetworkPanel *panel;
GtkWidget *toplevel;
client = net_object_get_client (NET_OBJECT (device_wifi));
panel = net_object_get_panel (NET_OBJECT (device_wifi));
toplevel = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (panel)));
cc_network_panel_connect_to_hidden_network (toplevel, client);
}
static void
connection_add_activate_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
NMActiveConnection *conn;
g_autoptr(GError) error = NULL;
conn = nm_client_add_and_activate_connection_finish (NM_CLIENT (source_object), res, &error);
if (!conn) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
nm_device_wifi_refresh_ui (user_data);
/* failed to activate */
g_warning ("Failed to add and activate connection '%d': %s",
error->code,
error->message);
}
return;
}
}
static void
connection_activate_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
if (!nm_client_activate_connection_finish (NM_CLIENT (source_object), res, &error)) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
nm_device_wifi_refresh_ui (user_data);
/* failed to activate */
g_debug ("Failed to add and activate connection '%d': %s",
error->code,
error->message);
}
return;
}
}
static gboolean
is_8021x (NMDevice *device,
const char *ap_object_path)
{
NM80211ApSecurityFlags wpa_flags, rsn_flags;
NMAccessPoint *ap;
ap = nm_device_wifi_get_access_point_by_path (NM_DEVICE_WIFI (device),
ap_object_path);
if (!ap)
return FALSE;
rsn_flags = nm_access_point_get_rsn_flags (ap);
if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
return TRUE;
wpa_flags = nm_access_point_get_wpa_flags (ap);
if (wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
return TRUE;
return FALSE;
}
static void
wireless_try_to_connect (NetDeviceWifi *device_wifi,
GBytes *ssid,
const gchar *ap_object_path)
{
const gchar *ssid_target;
NMDevice *device;
NMClient *client;
GCancellable *cancellable;
if (device_wifi->updating_device)
return;
if (ap_object_path == NULL || ap_object_path[0] == 0)
return;
device = net_device_get_nm_device (NET_DEVICE (device_wifi));
if (device == NULL)
return;
ssid_target = nm_utils_escape_ssid ((gpointer) g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
g_debug ("try to connect to WIFI network %s [%s]",
ssid_target, ap_object_path);
/* activate the connection */
client = net_object_get_client (NET_OBJECT (device_wifi));
cancellable = net_object_get_cancellable (NET_OBJECT (device_wifi));
if (!is_8021x (device, ap_object_path)) {
g_autoptr(GPermission) permission = NULL;
gboolean allowed_to_share = FALSE;
g_autoptr(NMConnection) partial = NULL;
permission = polkit_permission_new_sync ("org.freedesktop.NetworkManager.settings.modify.system",
NULL, NULL, NULL);
if (permission)
allowed_to_share = g_permission_get_allowed (permission);
if (!allowed_to_share) {
NMSettingConnection *s_con;
s_con = (NMSettingConnection *)nm_setting_connection_new ();
nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL);
partial = nm_simple_connection_new ();
nm_connection_add_setting (partial, NM_SETTING (s_con));
}
g_debug ("no existing connection found for %s, creating and activating one", ssid_target);
nm_client_add_and_activate_connection_async (client,
partial,
device,
ap_object_path,
cancellable,
connection_add_activate_cb,
device_wifi);
} else {
CcNetworkPanel *panel;
g_autoptr(GVariantBuilder) builder = NULL;
GVariant *parameters;
g_debug ("no existing connection found for %s, creating", ssid_target);
builder = g_variant_builder_new (G_VARIANT_TYPE ("av"));
g_variant_builder_add (builder, "v", g_variant_new_string ("connect-8021x-wifi"));
g_variant_builder_add (builder, "v", g_variant_new_string (nm_object_get_path (NM_OBJECT (device))));
g_variant_builder_add (builder, "v", g_variant_new_string (ap_object_path));
parameters = g_variant_new ("av", builder);
panel = net_object_get_panel (NET_OBJECT (device_wifi));
g_object_set (G_OBJECT (panel), "parameters", parameters, NULL);
}
}
static gchar *
get_hostname (void)
{
g_autoptr(GDBusConnection) bus = NULL;
g_autoptr(GVariant) res = NULL;
g_autoptr(GVariant) inner = NULL;
g_autoptr(GError) error = NULL;
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
if (bus == NULL) {
g_warning ("Failed to get system bus connection: %s", error->message);
return NULL;
}
res = g_dbus_connection_call_sync (bus,
"org.freedesktop.hostname1",
"/org/freedesktop/hostname1",
"org.freedesktop.DBus.Properties",
"Get",
g_variant_new ("(ss)",
"org.freedesktop.hostname1",
"PrettyHostname"),
(GVariantType*)"(v)",
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (res == NULL) {
g_warning ("Getting pretty hostname failed: %s", error->message);
return NULL;
}
g_variant_get (res, "(v)", &inner);
return g_variant_dup_string (inner, NULL);
}
static gboolean
is_hotspot_connection (NMConnection *connection)
{
NMSettingConnection *sc;
NMSettingWireless *sw;
NMSettingIPConfig *sip;
NMSetting *setting;
sc = nm_connection_get_setting_connection (connection);
if (g_strcmp0 (nm_setting_connection_get_connection_type (sc), "802-11-wireless") != 0) {
return FALSE;
}
sw = nm_connection_get_setting_wireless (connection);
if (g_strcmp0 (nm_setting_wireless_get_mode (sw), "adhoc") != 0 &&
g_strcmp0 (nm_setting_wireless_get_mode (sw), "ap") != 0) {
return FALSE;
}
setting = nm_connection_get_setting_by_name (connection, NM_SETTING_WIRELESS_SETTING_NAME);
if (!setting)
return FALSE;
sip = nm_connection_get_setting_ip4_config (connection);
if (g_strcmp0 (nm_setting_ip_config_get_method (sip), "shared") != 0) {
return FALSE;
}
return TRUE;
}
static void
show_hotspot_ui (NetDeviceWifi *device_wifi)
{
GtkWidget *widget;
/* show hotspot tab */
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder, "notebook_view"));
gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 1);
/* force switch to on as this succeeded */
device_wifi->updating_device = TRUE;
gtk_switch_set_active (device_wifi->hotspot_switch, TRUE);
device_wifi->updating_device = FALSE;
}
static void
activate_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
if (nm_client_activate_connection_finish (NM_CLIENT (source_object), res, &error) == NULL) {
g_warning ("Failed to add new connection: (%d) %s",
error->code,
error->message);
return;
}
/* show hotspot tab */
nm_device_wifi_refresh_ui (user_data);
}
static void
activate_new_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
NMActiveConnection *conn;
g_autoptr(GError) error = NULL;
conn = nm_client_add_and_activate_connection_finish (NM_CLIENT (source_object),
res, &error);
if (!conn) {
g_warning ("Failed to add new connection: (%d) %s",
error->code,
error->message);
return;
}
/* show hotspot tab */
nm_device_wifi_refresh_ui (user_data);
}
static NMConnection *
net_device_wifi_get_hotspot_connection (NetDeviceWifi *device_wifi)
{
GSList *connections, *l;
NMConnection *c = NULL;
connections = net_device_get_valid_connections (NET_DEVICE (device_wifi));
for (l = connections; l; l = l->next) {
NMConnection *tmp = l->data;
if (is_hotspot_connection (tmp)) {
c = tmp;
break;
}
}
g_slist_free (connections);
return c;
}
static void
overwrite_ssid_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
NMClient *client;
NMRemoteConnection *connection;
NMDevice *device;
NMConnection *c;
NetDeviceWifi *device_wifi;
GCancellable *cancellable;
connection = NM_REMOTE_CONNECTION (source_object);
if (!nm_remote_connection_commit_changes_finish (connection, res, &error)) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed to save hotspot's settings to disk: %s",
error->message);
return;
}
device_wifi = user_data;
device = net_device_get_nm_device (NET_DEVICE (device_wifi));
client = net_object_get_client (NET_OBJECT (device_wifi));
cancellable = net_object_get_cancellable (NET_OBJECT (device_wifi));
c = net_device_wifi_get_hotspot_connection (device_wifi);
g_debug ("activate existing hotspot connection\n");
nm_client_activate_connection_async (client,
c,
device,
NULL,
cancellable,
activate_cb,
device_wifi);
}
static void
start_hotspot (GtkButton *button, NetDeviceWifi *device_wifi)
{
NMDevice *device;
g_autofree gchar *active_ssid = NULL;
NMClient *client;
GtkWidget *window;
NMConnection *c;
g_autofree gchar *hostname = NULL;
g_autofree gchar *ssid = NULL;
gint response;
client = net_object_get_client (NET_OBJECT (device_wifi));
device = net_device_get_nm_device (NET_DEVICE (device_wifi));
window = gtk_widget_get_toplevel (GTK_WIDGET (button));
if (!device_wifi->hotspot_dialog)
device_wifi->hotspot_dialog = cc_wifi_hotspot_dialog_new (GTK_WINDOW (window));
cc_wifi_hotspot_dialog_set_device (device_wifi->hotspot_dialog, NM_DEVICE_WIFI (device));
hostname = get_hostname ();
ssid = pretty_hostname_to_ssid (hostname);
cc_wifi_hotspot_dialog_set_hostname (device_wifi->hotspot_dialog, ssid);
c = net_device_wifi_get_hotspot_connection (device_wifi);
if (c)
cc_wifi_hotspot_dialog_set_connection (device_wifi->hotspot_dialog, c);
response = gtk_dialog_run (GTK_DIALOG (device_wifi->hotspot_dialog));
if (response == GTK_RESPONSE_APPLY) {
NMConnection *connection;
GCancellable *cancellable;
cancellable = net_object_get_cancellable (NET_OBJECT (device_wifi));
connection = cc_wifi_hotspot_dialog_get_connection (device_wifi->hotspot_dialog);
if (NM_IS_REMOTE_CONNECTION (connection))
nm_remote_connection_commit_changes_async (NM_REMOTE_CONNECTION (connection),
TRUE,
cancellable,
overwrite_ssid_cb,
device_wifi);
else
nm_client_add_and_activate_connection_async (client,
connection,
device,
NULL,
cancellable,
activate_new_cb,
device_wifi);
}
gtk_widget_hide (GTK_WIDGET (device_wifi->hotspot_dialog));
}
static void
stop_shared_connection (NetDeviceWifi *device_wifi)
{
const GPtrArray *connections;
const GPtrArray *devices;
NMDevice *device;
gint i;
NMActiveConnection *c;
NMClient *client;
gboolean found = FALSE;
device = net_device_get_nm_device (NET_DEVICE (device_wifi));
client = net_object_get_client (NET_OBJECT (device_wifi));
connections = nm_client_get_active_connections (client);
for (i = 0; connections && i < connections->len; i++) {
c = (NMActiveConnection *)connections->pdata[i];
devices = nm_active_connection_get_devices (c);
if (devices && devices->pdata[0] == device) {
nm_client_deactivate_connection (client, c, NULL, NULL);
found = TRUE;
break;
}
}
if (!found) {
g_warning ("Could not stop hotspot connection as no connection attached to the device could be found.");
device_wifi->updating_device = TRUE;
gtk_switch_set_active (device_wifi->hotspot_switch, TRUE);
device_wifi->updating_device = FALSE;
return;
}
nm_device_wifi_refresh_ui (device_wifi);
}
static void
stop_hotspot_response_cb (GtkWidget *dialog, gint response, NetDeviceWifi *device_wifi)
{
if (response == GTK_RESPONSE_OK) {
stop_shared_connection (device_wifi);
} else {
device_wifi->updating_device = TRUE;
gtk_switch_set_active (device_wifi->hotspot_switch, TRUE);
device_wifi->updating_device = FALSE;
}
gtk_widget_destroy (dialog);
}
static void
switch_hotspot_changed_cb (GtkSwitch *sw,
GParamSpec *pspec,
NetDeviceWifi *device_wifi)
{
GtkWidget *dialog;
GtkWidget *window;
CcNetworkPanel *panel;
if (device_wifi->updating_device)
return;
panel = net_object_get_panel (NET_OBJECT (device_wifi));
window = gtk_widget_get_toplevel (GTK_WIDGET (panel));
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_OTHER,
GTK_BUTTONS_NONE,
_("Stop hotspot and disconnect any users?"));
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Stop Hotspot"), GTK_RESPONSE_OK,
NULL);
g_signal_connect (dialog, "response",
G_CALLBACK (stop_hotspot_response_cb), device_wifi);
gtk_window_present (GTK_WINDOW (dialog));
}
static void
show_wifi_list (NetDeviceWifi *device_wifi)
{
GtkWidget *widget;
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder, "notebook_view"));
gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 0);
}
static void
net_device_wifi_constructed (GObject *object)
{
NetDeviceWifi *device_wifi = NET_DEVICE_WIFI (object);
NMClient *client;
NMClientPermissionResult perm;
NMDevice *nm_device;
NMDeviceWifiCapabilities caps;
GtkWidget *list_container;
GtkWidget *list;
GtkWidget *widget;
G_OBJECT_CLASS (net_device_wifi_parent_class)->constructed (object);
client = net_object_get_client (NET_OBJECT (device_wifi));
g_signal_connect_object (client, "notify::wireless-enabled",
G_CALLBACK (wireless_enabled_toggled), device_wifi, 0);
nm_device = net_device_get_nm_device (NET_DEVICE (device_wifi));
list_container = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder, "listbox_box"));
list = GTK_WIDGET (cc_wifi_connection_list_new (client, NM_DEVICE_WIFI (nm_device), TRUE, TRUE, FALSE));
gtk_widget_show (list);
gtk_container_add (GTK_CONTAINER (list_container), list);
gtk_list_box_set_header_func (GTK_LIST_BOX (list), cc_list_box_update_header_func, NULL, NULL);
gtk_list_box_set_sort_func (GTK_LIST_BOX (list), (GtkListBoxSortFunc)ap_sort, NULL, NULL);
g_signal_connect (list, "row-activated",
G_CALLBACK (ap_activated), device_wifi);
g_signal_connect_swapped (list, "configure",
G_CALLBACK (show_details_for_row),
device_wifi);
/* only enable the button if the user can create a hotspot */
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder,
"start_hotspot_button"));
perm = nm_client_get_permission_result (client, NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN);
caps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (nm_device));
if (perm != NM_CLIENT_PERMISSION_RESULT_YES &&
perm != NM_CLIENT_PERMISSION_RESULT_AUTH) {
gtk_widget_set_tooltip_text (widget, _("System policy prohibits use as a Hotspot"));
gtk_widget_set_sensitive (widget, FALSE);
} else if (!(caps & (NM_WIFI_DEVICE_CAP_AP | NM_WIFI_DEVICE_CAP_ADHOC))) {
gtk_widget_set_tooltip_text (widget, _("Wireless device does not support Hotspot mode"));
gtk_widget_set_sensitive (widget, FALSE);
} else
gtk_widget_set_sensitive (widget, TRUE);
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder, "heading_list"));
g_object_bind_property (device_wifi, "title", widget, "label", 0);
nm_device_wifi_refresh_ui (device_wifi);
}
static void
net_device_wifi_finalize (GObject *object)
{
NetDeviceWifi *device_wifi = NET_DEVICE_WIFI (object);
if (device_wifi->cancellable) {
g_cancellable_cancel (device_wifi->cancellable);
g_clear_object (&device_wifi->cancellable);
}
disable_scan_timeout (device_wifi);
g_clear_pointer (&device_wifi->details_dialog, gtk_widget_destroy);
g_object_unref (device_wifi->builder);
g_free (device_wifi->selected_ssid_title);
g_free (device_wifi->selected_connection_id);
g_free (device_wifi->selected_ap_id);
G_OBJECT_CLASS (net_device_wifi_parent_class)->finalize (object);
}
static void
device_wifi_edit (NetObject *object)
{
const gchar *uuid;
g_autofree gchar *cmdline = NULL;
g_autoptr(GError) error = NULL;
NetDeviceWifi *device = NET_DEVICE_WIFI (object);
NMClient *client;
NMRemoteConnection *connection;
client = net_object_get_client (object);
connection = nm_client_get_connection_by_path (client, device->selected_connection_id);
if (connection == NULL) {
g_warning ("failed to get remote connection");
return;
}
uuid = nm_connection_get_uuid (NM_CONNECTION (connection));
cmdline = g_strdup_printf ("nm-connection-editor --edit %s", uuid);
g_debug ("Launching '%s'\n", cmdline);
if (!g_spawn_command_line_async (cmdline, &error))
g_warning ("Failed to launch nm-connection-editor: %s", error->message);
}
static void
net_device_wifi_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NetDeviceWifi *self = NET_DEVICE_WIFI (object);
switch (prop_id) {
case PROP_SCANNING:
g_value_set_boolean (value, self->scanning);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
net_device_wifi_class_init (NetDeviceWifiClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NetObjectClass *parent_class = NET_OBJECT_CLASS (klass);
object_class->finalize = net_device_wifi_finalize;
object_class->constructed = net_device_wifi_constructed;
object_class->get_property = net_device_wifi_get_property;
parent_class->add_to_stack = device_wifi_proxy_add_to_stack;
parent_class->refresh = device_wifi_refresh;
parent_class->edit = device_wifi_edit;
g_object_class_install_property (object_class,
PROP_SCANNING,
g_param_spec_boolean ("scanning",
"Scanning",
"Whether the device is scanning for access points",
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
}
static void
really_forgotten (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(CcWifiConnectionList) list = user_data;
g_autoptr(GError) error = NULL;
cc_wifi_connection_list_thaw (list);
if (!nm_remote_connection_delete_finish (NM_REMOTE_CONNECTION (source_object), res, &error))
g_warning ("failed to delete connection %s: %s",
nm_object_get_path (NM_OBJECT (source_object)),
error->message);
}
static void
really_forget (GtkDialog *dialog, gint response, gpointer data)
{
GtkWidget *forget = data;
CcWifiConnectionRow *row;
GList *rows;
GList *r;
NMRemoteConnection *connection;
NetDeviceWifi *device_wifi;
GCancellable *cancellable;
gtk_widget_destroy (GTK_WIDGET (dialog));
if (response != GTK_RESPONSE_OK)
return;
device_wifi = NET_DEVICE_WIFI (g_object_get_data (G_OBJECT (forget), "net"));
cancellable = net_object_get_cancellable (NET_OBJECT (device_wifi));
rows = g_object_steal_data (G_OBJECT (forget), "rows");
for (r = rows; r; r = r->next) {
row = r->data;
connection = NM_REMOTE_CONNECTION (cc_wifi_connection_row_get_connection (row));
nm_remote_connection_delete_async (connection, cancellable, really_forgotten, g_object_ref (data));
gtk_widget_hide (GTK_WIDGET (row));
}
g_list_free (rows);
}
static void
forget_selected (GtkButton *forget, CcWifiConnectionList *list)
{
GtkWidget *window;
GtkWidget *dialog;
window = gtk_widget_get_toplevel (GTK_WIDGET (forget));
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_OTHER,
GTK_BUTTONS_NONE,
NULL);
gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog),
_("Network details for the selected networks, including passwords and any custom configuration will be lost."));
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Forget"), GTK_RESPONSE_OK,
NULL);
g_signal_connect (dialog, "response",
G_CALLBACK (really_forget), list);
gtk_window_present (GTK_WINDOW (dialog));
}
static void
check_toggled (CcWifiConnectionRow *row, GParamSpec *pspec, CcWifiConnectionList *list)
{
GtkWidget *forget;
gboolean active;
GList *rows;
active = cc_wifi_connection_row_get_checked (row);
rows = g_object_steal_data (G_OBJECT (list), "rows");
if (active) {
cc_wifi_connection_list_freeze (list);
rows = g_list_prepend (rows, row);
} else {
cc_wifi_connection_list_thaw (list);
rows = g_list_remove (rows, row);
}
g_object_set_data_full (G_OBJECT (list), "rows", rows, (GDestroyNotify)g_list_free);
forget = g_object_get_data (G_OBJECT (list), "forget");
gtk_widget_set_sensitive (forget, rows != NULL);
}
static gint
history_sort (gconstpointer a, gconstpointer b, gpointer data)
{
guint64 ta, tb;
NMConnection *ca, *cb;
NMSettingConnection *sc;
ca = cc_wifi_connection_row_get_connection (CC_WIFI_CONNECTION_ROW ((gpointer) a));
cb = cc_wifi_connection_row_get_connection (CC_WIFI_CONNECTION_ROW ((gpointer) b));
if (ca) {
sc = nm_connection_get_setting_connection (ca);
ta = nm_setting_connection_get_timestamp (sc);
} else {
ta = 0;
}
if (cb) {
sc = nm_connection_get_setting_connection (cb);
tb = nm_setting_connection_get_timestamp (sc);
} else {
tb = 0;
}
if (ta > tb) return -1;
if (tb > ta) return 1;
return 0;
}
static gint
ap_sort (gconstpointer a, gconstpointer b, gpointer data)
{
NMAccessPoint *apa, *apb;
guint sa, sb;
apa = cc_wifi_connection_row_best_access_point (CC_WIFI_CONNECTION_ROW ((gpointer) a));
apb = cc_wifi_connection_row_best_access_point (CC_WIFI_CONNECTION_ROW ((gpointer) b));
if (apa)
sa = nm_access_point_get_strength (apa);
else
sa = 0;
if (apb)
sb = nm_access_point_get_strength (apb);
else
sb = 0;
if (sa > sb) return -1;
if (sb > sa) return 1;
return 0;
}
static void
show_details_for_row (NetDeviceWifi *device_wifi, CcWifiConnectionRow *row, CcWifiConnectionList *list)
{
NMConnection *connection;
NMAccessPoint *ap;
GtkWidget *window;
NetConnectionEditor *editor;
NMClient *client;
NMDevice *device;
window = gtk_widget_get_toplevel (GTK_WIDGET (row));
connection = cc_wifi_connection_row_get_connection (row);
ap = cc_wifi_connection_row_best_access_point (row);
device = net_device_get_nm_device (NET_DEVICE (device_wifi));
client = net_object_get_client (NET_OBJECT (device_wifi));
editor = net_connection_editor_new (GTK_WINDOW (window), connection, device, ap, client);
net_connection_editor_run (editor);
}
static void
on_connection_list_row_added_cb (NetDeviceWifi *device_wifi,
CcWifiConnectionRow *row,
CcWifiConnectionList *list)
{
g_signal_connect (row, "notify::checked",
G_CALLBACK (check_toggled), list);
}
static void
on_connection_list_row_removed_cb (NetDeviceWifi *device_wifi,
CcWifiConnectionRow *row,
CcWifiConnectionList *list)
{
GList *rows = g_object_steal_data (G_OBJECT (list), "rows");
GList *item;
GtkWidget *forget;
item = g_list_find (rows, row);
if (item)
{
rows = g_list_remove (rows, row);
cc_wifi_connection_list_thaw (list);
}
g_object_set_data_full (G_OBJECT (list), "rows", rows, (GDestroyNotify)g_list_free);
forget = g_object_get_data (G_OBJECT (list), "forget");
gtk_widget_set_sensitive (forget, rows != NULL);
}
static void
on_connection_list_row_activated_cb (NetDeviceWifi *device_wifi,
CcWifiConnectionRow *row,
CcWifiConnectionList *list)
{
cc_wifi_connection_row_set_checked (row, !cc_wifi_connection_row_get_checked (row));
}
static void
open_history (NetDeviceWifi *device_wifi)
{
GtkWidget *dialog;
GtkWidget *window;
CcNetworkPanel *panel;
GtkWidget *forget;
GtkWidget *header;
GtkWidget *swin;
GtkWidget *content_area;
GtkWidget *separator;
NMDevice *nm_device;
GtkWidget *list;
GList *list_rows;
dialog = g_object_new (HDY_TYPE_DIALOG, "use-header-bar", 1, NULL);
panel = net_object_get_panel (NET_OBJECT (device_wifi));
window = gtk_widget_get_toplevel (GTK_WIDGET (panel));
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
gtk_window_set_title (GTK_WINDOW (dialog), _("Known Wi-Fi Networks"));
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400);
/* Dialog's header */
header = gtk_header_bar_new ();
gtk_widget_show (header);
gtk_header_bar_set_title (GTK_HEADER_BAR (header), _("Known Wi-Fi Networks"));
gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (header), TRUE);
gtk_window_set_titlebar (GTK_WINDOW (dialog), header);
g_signal_connect_swapped (dialog, "response",
G_CALLBACK (gtk_widget_destroy), dialog);
g_signal_connect_swapped (dialog, "delete-event",
G_CALLBACK (gtk_widget_destroy), dialog);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
gtk_container_set_border_width (GTK_CONTAINER (content_area), 0);
swin = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show (swin);
gtk_widget_set_vexpand (swin, TRUE);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin), GTK_SHADOW_NONE);
gtk_container_add (GTK_CONTAINER (content_area), swin);
nm_device = net_device_get_nm_device (NET_DEVICE (device_wifi));
list = GTK_WIDGET (cc_wifi_connection_list_new (net_object_get_client (NET_OBJECT (device_wifi)),
NM_DEVICE_WIFI (nm_device),
FALSE, FALSE, TRUE));
gtk_widget_show (list);
gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_NONE);
gtk_list_box_set_header_func (GTK_LIST_BOX (list), cc_list_box_update_header_func, NULL, NULL);
gtk_list_box_set_sort_func (GTK_LIST_BOX (list), (GtkListBoxSortFunc)history_sort, NULL, NULL);
gtk_container_add (GTK_CONTAINER (swin), list);
/* Horizontal separator */
separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
gtk_widget_show (separator);
gtk_container_add (GTK_CONTAINER (content_area), separator);
/* translators: This is the label for the "Forget wireless network" functionality */
forget = gtk_button_new_with_mnemonic (C_("Wi-Fi Network", "_Forget"));
gtk_widget_show (forget);
gtk_widget_set_halign (forget, GTK_ALIGN_START);
gtk_widget_set_margin_top (forget, 6);
gtk_widget_set_margin_bottom (forget, 6);
gtk_widget_set_margin_start (forget, 6);
gtk_widget_set_sensitive (forget, FALSE);
gtk_style_context_add_class (gtk_widget_get_style_context (forget), "destructive-action");
g_signal_connect (forget, "clicked",
G_CALLBACK (forget_selected), list);
gtk_container_add (GTK_CONTAINER (content_area), forget);
g_object_set_data (G_OBJECT (list), "forget", forget);
g_object_set_data (G_OBJECT (list), "net", device_wifi);
g_signal_connect_swapped (list, "add",
G_CALLBACK (on_connection_list_row_added_cb),
device_wifi);
g_signal_connect_swapped (list, "remove",
G_CALLBACK (on_connection_list_row_removed_cb),
device_wifi);
g_signal_connect_swapped (list, "row-activated",
G_CALLBACK (on_connection_list_row_activated_cb),
device_wifi);
g_signal_connect_swapped (list, "configure",
G_CALLBACK (show_details_for_row),
device_wifi);
list_rows = gtk_container_get_children (GTK_CONTAINER (list));
while (list_rows)
{
on_connection_list_row_added_cb (device_wifi,
CC_WIFI_CONNECTION_ROW (list_rows->data),
CC_WIFI_CONNECTION_LIST (list));
list_rows = g_list_delete_link (list_rows, list_rows);
}
gtk_window_present (GTK_WINDOW (dialog));
}
static void
ap_activated (GtkListBox *list, GtkListBoxRow *row, NetDeviceWifi *device_wifi)
{
CcWifiConnectionRow *c_row;
NMConnection *connection;
NMAccessPoint *ap;
NMClient *client;
NMDevice *nm_device;
GCancellable *cancellable;
/* The mockups want a row to connecto hidden networks; this could
* be handeled here. */
if (!CC_IS_WIFI_CONNECTION_ROW (row))
return;
c_row = CC_WIFI_CONNECTION_ROW (row);
connection = cc_wifi_connection_row_get_connection (c_row);
ap = cc_wifi_connection_row_best_access_point (c_row);
if (ap != NULL) {
if (connection != NULL) {
client = net_object_get_client (NET_OBJECT (device_wifi));
nm_device = net_device_get_nm_device (NET_DEVICE (device_wifi));
cancellable = net_object_get_cancellable (NET_OBJECT (device_wifi));
nm_client_activate_connection_async (client,
connection,
nm_device, NULL, cancellable,
connection_activate_cb, device_wifi);
} else {
GBytes *ssid;
const gchar *object_path;
ssid = nm_access_point_get_ssid (ap);
object_path = nm_object_get_path (NM_OBJECT (ap));
wireless_try_to_connect (device_wifi, ssid, object_path);
}
}
}
static void
net_device_wifi_init (NetDeviceWifi *device_wifi)
{
g_autoptr(GError) error = NULL;
GtkWidget *widget;
device_wifi->builder = gtk_builder_new ();
gtk_builder_add_from_resource (device_wifi->builder,
"/org/gnome/control-center/network/network-wifi.ui",
&error);
if (error != NULL) {
g_warning ("Could not load interface file: %s", error->message);
return;
}
device_wifi->cancellable = g_cancellable_new ();
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder,
"details_dialog"));
device_wifi->details_dialog = widget;
/* setup wifi views */
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder,
"device_off_switch"));
g_signal_connect (widget, "notify::active",
G_CALLBACK (device_off_toggled), device_wifi);
/* setup view */
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder,
"notebook_view"));
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 0);
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder,
"start_hotspot_button"));
g_signal_connect (widget, "clicked",
G_CALLBACK (start_hotspot), device_wifi);
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder,
"connect_hidden_button"));
g_signal_connect_swapped (widget, "clicked",
G_CALLBACK (connect_to_hidden_network), device_wifi);
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder,
"history_button"));
g_signal_connect_swapped (widget, "clicked",
G_CALLBACK (open_history), device_wifi);
widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder,
"switch_hotspot_off"));
device_wifi->hotspot_switch = GTK_SWITCH (widget);
g_signal_connect (widget, "notify::active",
G_CALLBACK (switch_hotspot_changed_cb), device_wifi);
}