[gnome-control-center] network: Add new hotspot creation dialog



commit 642be837984210b3683ccb1d6e3802854fdea02a
Author: Mohammed Sadiq <sadiq sadiqpk org>
Date:   Tue Sep 17 12:15:11 2019 +0000

    network: Add new hotspot creation dialog

 panels/network/cc-wifi-hotspot-dialog.c  | 519 +++++++++++++++++++++++++++++++
 panels/network/cc-wifi-hotspot-dialog.h  |  44 +++
 panels/network/cc-wifi-hotspot-dialog.ui | 141 +++++++++
 panels/network/meson.build               |   4 +-
 panels/network/net-device-wifi.c         | 312 +++----------------
 panels/network/network.gresource.xml     |   1 +
 6 files changed, 748 insertions(+), 273 deletions(-)
---
diff --git a/panels/network/cc-wifi-hotspot-dialog.c b/panels/network/cc-wifi-hotspot-dialog.c
new file mode 100644
index 000000000..6f49dfa6f
--- /dev/null
+++ b/panels/network/cc-wifi-hotspot-dialog.c
@@ -0,0 +1,519 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wifi-hotspot-dialog.c
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ *   Mohammed Sadiq <sadiq sadiqpk org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-wifi-hotspot-dialog"
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <libmm-glib.h>
+
+#include "list-box-helper.h"
+#include "connection-editor/ui-helpers.h"
+#include "cc-wifi-hotspot-dialog.h"
+#include "cc-network-resources.h"
+
+/**
+ * @short_description: WWAN network type selection dialog
+ */
+
+struct _CcWifiHotspotDialog
+{
+  GtkMessageDialog parent_instance;
+
+  GtkLabel        *connection_label;
+  GtkEntry        *name_entry;
+  GtkEntry        *password_entry;
+  GtkLabel        *error_label;
+  GtkButton       *ok_button;
+
+  NMDeviceWifi    *device;
+  NMConnection    *connection;
+  gchar           *host_name;
+  gboolean         wpa_supported; /* WPA/WPA2 supported */
+};
+
+G_DEFINE_TYPE (CcWifiHotspotDialog, cc_wifi_hotspot_dialog, GTK_TYPE_MESSAGE_DIALOG)
+
+static gchar *
+get_random_wpa_key (void)
+{
+  gchar *key;
+  gint i;
+
+  key = g_malloc (10 * sizeof (key));
+  for (i = 0; i < 8; i++)
+    {
+      gint c = 0;
+      /* too many non alphanumeric characters are hard to remember for humans */
+      while (!g_ascii_isalnum (c))
+        c = g_random_int_range (33, 126);
+
+    key[i] = (gchar) c;
+  }
+  key[i] = '\0';
+
+  return key;
+}
+
+static gchar *
+get_random_wep_key (void)
+{
+  const gchar *hexdigits = "0123456789abcdef";
+  gchar *key;
+  gint i;
+
+  key = g_malloc (12 * sizeof (key));
+
+  /* generate a 10-digit hex WEP key */
+  for (i = 0; i < 10; i++)
+    {
+      gint digit;
+      digit = g_random_int_range (0, 16);
+      key[i] = hexdigits[digit];
+    }
+
+  key[i] = '\0';
+
+  return key;
+}
+
+static void
+wifi_hotspot_dialog_update_main_label (CcWifiHotspotDialog *self)
+{
+  NMAccessPoint *ap;
+  GBytes *ssid = NULL;
+  g_autofree gchar *active_ssid = NULL;
+  g_autofree gchar *escape = NULL;
+  g_autofree gchar *label = NULL;
+
+  g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+  if (!self->device)
+    return;
+
+  ap = nm_device_wifi_get_active_access_point (self->device);
+
+  if (ap)
+    ssid = nm_access_point_get_ssid (ap);
+  if (ssid)
+    active_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
+
+  if (!active_ssid || !*active_ssid)
+    return;
+
+  escape = g_markup_escape_text (active_ssid, -1);
+  /* TRANSLATORS: ā€˜%sā€™ is a Wi-Fi Network(SSID) name */
+  label = g_strdup_printf (_("Turning on the hotspot will disconnect from <b>%s</b>, "
+                             "and it will not be possible to access the internet through Wi-Fi."), escape);
+  gtk_label_set_markup (self->connection_label, label);
+}
+
+static void
+wifi_hotspot_dialog_update_entries (CcWifiHotspotDialog *self)
+{
+  NMSettingWirelessSecurity *security_setting;
+  NMSettingWireless *setting;
+  GBytes *ssid;
+  g_autoptr(GVariant) secrets = NULL;
+  g_autoptr(GError) error = NULL;
+  g_autofree gchar *ssid_text = NULL;
+  const gchar *key;
+
+  g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+  gtk_entry_set_text (self->name_entry, "");
+  gtk_entry_set_text (self->password_entry, "");
+
+  if (!self->connection)
+    return;
+
+  setting = nm_connection_get_setting_wireless (self->connection);
+  security_setting = nm_connection_get_setting_wireless_security (self->connection);
+
+  ssid = nm_setting_wireless_get_ssid (setting);
+  ssid_text = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
+
+  if (!ssid_text && self->host_name)
+    ssid_text = g_strdup (self->host_name);
+
+  if (ssid_text)
+    gtk_entry_set_text (self->name_entry, ssid_text);
+
+  if (!NM_IS_REMOTE_CONNECTION (self->connection))
+    return;
+
+  /* Secrets may not be already loaded, we have to manually load it. */
+  secrets = nm_remote_connection_get_secrets (NM_REMOTE_CONNECTION (self->connection),
+                                              NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+                                              NULL, &error);
+  if (error)
+    {
+      g_warning ("Error loading secrets: %s", error->message);
+      return;
+    }
+
+  nm_connection_update_secrets (self->connection,
+                                NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+                                secrets, &error);
+  if (error)
+    {
+      g_warning ("Error updating secrets: %s", error->message);
+      return;
+    }
+
+  if (self->wpa_supported)
+    key = nm_setting_wireless_security_get_psk (security_setting);
+  else
+    key = nm_setting_wireless_security_get_wep_key (security_setting, 0);
+
+  if (key)
+    gtk_entry_set_text (self->password_entry, key);
+
+  nm_connection_clear_secrets (self->connection);
+}
+
+static gboolean
+hotspot_password_is_valid (CcWifiHotspotDialog *self,
+                           const gchar         *password)
+{
+  g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+  if (!self->device)
+    return FALSE;
+
+  if (!password || !*password)
+    return TRUE;
+
+  if (self->wpa_supported)
+    return nm_utils_wpa_psk_valid (password);
+  else
+    return nm_utils_wep_key_valid (password, NM_WEP_KEY_TYPE_KEY);
+}
+
+static void
+hotspot_entry_changed_cb (CcWifiHotspotDialog *self)
+{
+  const gchar *ssid, *password, *error_label;
+  gboolean valid_ssid, valid_password;
+
+  g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+  valid_ssid = valid_password = FALSE;
+  ssid = gtk_entry_get_text (self->name_entry);
+  password = gtk_entry_get_text (self->password_entry);
+
+  if (ssid && *ssid)
+    {
+      valid_ssid = TRUE;
+      widget_unset_error (GTK_WIDGET (self->name_entry));
+    }
+  else
+    widget_set_error (GTK_WIDGET (self->name_entry));
+
+  valid_password = hotspot_password_is_valid (self, password);
+
+  if (valid_password)
+    {
+      error_label = "";
+      widget_unset_error (GTK_WIDGET (self->password_entry));
+    }
+  else
+    {
+      error_label = _("Must have a minimum of 8 characters");
+      widget_set_error (GTK_WIDGET(self->password_entry));
+    }
+
+  gtk_label_set_label (self->error_label, error_label);
+  gtk_widget_set_sensitive (GTK_WIDGET (self->ok_button),
+                            valid_ssid && valid_password);
+}
+
+static void
+generate_password_clicked_cb (CcWifiHotspotDialog *self)
+{
+  g_autofree gchar *key = NULL;
+
+  g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+  if (self->wpa_supported)
+    key = get_random_wpa_key ();
+  else
+    key = get_random_wep_key ();
+
+  gtk_entry_set_text (self->password_entry, key);
+}
+
+static void
+hotspot_update_wireless_settings (CcWifiHotspotDialog *self)
+{
+  NMSettingWireless *setting;
+  g_autoptr(GBytes) ssid = NULL;
+  const gchar *ssid_text;
+  NMDeviceWifiCapabilities capabilities;
+
+  g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+  if (nm_connection_get_setting_wireless (self->connection) == NULL)
+    nm_connection_add_setting (self->connection, nm_setting_wireless_new ());
+
+  setting = nm_connection_get_setting_wireless (self->connection);
+
+  capabilities = nm_device_wifi_get_capabilities (self->device);
+  if (capabilities & NM_WIFI_DEVICE_CAP_AP)
+    g_object_set (setting, "mode", "ap", NULL);
+  else
+    g_object_set (setting, "mode", "adhoc", NULL);
+
+  ssid_text = gtk_entry_get_text (self->name_entry);
+  ssid = g_bytes_new (ssid_text, strlen (ssid_text));
+  g_object_set (setting, "ssid", ssid, NULL);
+}
+
+static void
+hotspot_update_wireless_security_settings (CcWifiHotspotDialog *self)
+{
+  NMSettingWirelessSecurity *setting;
+  const gchar *value, *key_type;
+
+  g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+  if (nm_connection_get_setting_wireless_security (self->connection) == NULL)
+    nm_connection_add_setting (self->connection, nm_setting_wireless_security_new ());
+
+  setting = nm_connection_get_setting_wireless_security (self->connection);
+  nm_setting_wireless_security_clear_protos (setting);
+  nm_setting_wireless_security_clear_pairwise (setting);
+  nm_setting_wireless_security_clear_groups (setting);
+  value = gtk_entry_get_text (self->password_entry);
+
+  if (self->wpa_supported)
+    key_type = "psk";
+  else
+    key_type = "wep-key0";
+
+  if (self->wpa_supported)
+    g_object_set (setting, "key-mgmt", "wpa-psk", NULL);
+  else
+    g_object_set (setting,
+                  "key-mgmt", "none",
+                  "wep-key-type", NM_WEP_KEY_TYPE_KEY,
+                  NULL);
+
+  if (!value || !*value)
+    {
+      g_autofree gchar *key = NULL;
+
+      if (self->wpa_supported)
+        key = get_random_wpa_key ();
+      else
+        key = get_random_wep_key ();
+
+      g_object_set (setting, key_type, key, NULL);
+    }
+  else
+    g_object_set (setting, key_type, value, NULL);
+
+  if (self->wpa_supported)
+    {
+      NMDeviceWifiCapabilities caps;
+
+      caps = nm_device_wifi_get_capabilities (self->device);
+
+      if (caps & NM_WIFI_DEVICE_CAP_RSN)
+        {
+          nm_setting_wireless_security_add_proto (setting, "rsn");
+          nm_setting_wireless_security_add_pairwise (setting, "ccmp");
+          nm_setting_wireless_security_add_group (setting, "ccmp");
+        }
+      else if (caps & NM_WIFI_DEVICE_CAP_WPA)
+        {
+          nm_setting_wireless_security_add_proto (setting, "wpa");
+          nm_setting_wireless_security_add_pairwise (setting, "tkip");
+          nm_setting_wireless_security_add_group (setting, "tkip");
+        }
+    }
+}
+
+static void
+cc_wifi_hotspot_dialog_finalize (GObject *object)
+{
+  CcWifiHotspotDialog *self = (CcWifiHotspotDialog *)object;
+
+  g_free (self->host_name);
+  g_clear_object (&self->device);
+  g_clear_object (&self->connection);
+
+  G_OBJECT_CLASS (cc_wifi_hotspot_dialog_parent_class)->finalize (object);
+}
+
+static void
+cc_wifi_hotspot_dialog_show (GtkWidget *widget)
+{
+  CcWifiHotspotDialog *self = (CcWifiHotspotDialog *)widget;
+  g_warn_if_fail (self->device != NULL);
+
+  gtk_widget_grab_focus (GTK_WIDGET (self->ok_button));
+  wifi_hotspot_dialog_update_entries (self);
+
+  if (!self->connection)
+    if (self->host_name)
+      gtk_entry_set_text (self->name_entry, self->host_name);
+
+  GTK_WIDGET_CLASS (cc_wifi_hotspot_dialog_parent_class)->show (widget);
+}
+
+static void
+cc_wifi_hotspot_dialog_response (GtkDialog *dialog,
+                                 gint       response_id)
+{
+  CcWifiHotspotDialog *self = CC_WIFI_HOTSPOT_DIALOG (dialog);
+  NMSetting *setting;
+
+  if (response_id != GTK_RESPONSE_APPLY)
+    return;
+
+  if (!self->connection)
+    self->connection = NM_CONNECTION (nm_simple_connection_new ());
+
+  if (nm_connection_get_setting_connection (self->connection) == NULL)
+    {
+      setting = nm_setting_connection_new ();
+      g_object_set (setting,
+                    "type", "802-11-wireless",
+                    "id", "Hotspot",
+                    "autoconnect", FALSE,
+                    NULL);
+      nm_connection_add_setting (self->connection, setting);
+    }
+
+  if (nm_connection_get_setting_ip4_config (self->connection) == NULL)
+    {
+      setting = nm_setting_ip4_config_new ();
+      g_object_set (setting, "method", "shared", NULL);
+      nm_connection_add_setting (self->connection, setting);
+    }
+
+  hotspot_update_wireless_settings (self);
+  hotspot_update_wireless_security_settings (self);
+}
+
+static void
+cc_wifi_hotspot_dialog_class_init (CcWifiHotspotDialogClass *klass)
+{
+  GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = cc_wifi_hotspot_dialog_finalize;
+
+  widget_class->show = cc_wifi_hotspot_dialog_show;
+  dialog_class->response = cc_wifi_hotspot_dialog_response;
+
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                               
"/org/gnome/control-center/network/cc-wifi-hotspot-dialog.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, CcWifiHotspotDialog, connection_label);
+  gtk_widget_class_bind_template_child (widget_class, CcWifiHotspotDialog, name_entry);
+  gtk_widget_class_bind_template_child (widget_class, CcWifiHotspotDialog, password_entry);
+  gtk_widget_class_bind_template_child (widget_class, CcWifiHotspotDialog, error_label);
+  gtk_widget_class_bind_template_child (widget_class, CcWifiHotspotDialog, ok_button);
+
+  gtk_widget_class_bind_template_callback (widget_class, hotspot_entry_changed_cb);
+  gtk_widget_class_bind_template_callback (widget_class, generate_password_clicked_cb);
+}
+
+static void
+cc_wifi_hotspot_dialog_init (CcWifiHotspotDialog *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcWifiHotspotDialog *
+cc_wifi_hotspot_dialog_new (GtkWindow *parent_window)
+{
+  g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
+
+  return g_object_new (CC_TYPE_WIFI_HOTSPOT_DIALOG,
+                       "transient-for", parent_window,
+                       "message-type", GTK_MESSAGE_OTHER,
+                       NULL);
+}
+
+void
+cc_wifi_hotspot_dialog_set_hostname (CcWifiHotspotDialog *self,
+                                     const gchar         *host_name)
+{
+  g_return_if_fail (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+  g_free (self->host_name);
+  self->host_name = g_strdup (host_name);
+}
+
+void
+cc_wifi_hotspot_dialog_set_device (CcWifiHotspotDialog *self,
+                                   NMDeviceWifi        *device)
+{
+  g_return_if_fail (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+  g_return_if_fail (NM_IS_DEVICE_WIFI (device));
+
+  g_set_object (&self->device, device);
+
+  if (device)
+    {
+      NMDeviceWifiCapabilities caps;
+
+      caps = nm_device_wifi_get_capabilities (device);
+      self->wpa_supported = FALSE;
+
+      if (caps & NM_WIFI_DEVICE_CAP_AP)
+        if (caps & (NM_WIFI_DEVICE_CAP_RSN | NM_WIFI_DEVICE_CAP_WPA))
+          self->wpa_supported = TRUE;
+    }
+
+  wifi_hotspot_dialog_update_main_label (self);
+}
+
+NMConnection *
+cc_wifi_hotspot_dialog_get_connection (CcWifiHotspotDialog *self)
+{
+  g_return_val_if_fail (CC_IS_WIFI_HOTSPOT_DIALOG (self), NULL);
+
+  return self->connection;
+}
+
+void
+cc_wifi_hotspot_dialog_set_connection (CcWifiHotspotDialog *self,
+                                       NMConnection        *connection)
+{
+  NMSettingWireless *setting;
+
+  g_return_if_fail (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+  g_return_if_fail (NM_IS_CONNECTION (connection));
+
+  setting = nm_connection_get_setting_wireless (connection);
+  g_return_if_fail (setting);
+
+  g_set_object (&self->connection, connection);
+}
diff --git a/panels/network/cc-wifi-hotspot-dialog.h b/panels/network/cc-wifi-hotspot-dialog.h
new file mode 100644
index 000000000..585d7f1d0
--- /dev/null
+++ b/panels/network/cc-wifi-hotspot-dialog.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* wifi-hotspot-dialog.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ *   Mohammed Sadiq <sadiq sadiqpk org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WIFI_HOTSPOT_DIALOG (cc_wifi_hotspot_dialog_get_type())
+G_DECLARE_FINAL_TYPE (CcWifiHotspotDialog, cc_wifi_hotspot_dialog, CC, WIFI_HOTSPOT_DIALOG, GtkMessageDialog)
+
+CcWifiHotspotDialog *cc_wifi_hotspot_dialog_new            (GtkWindow           *parent_window);
+void                 cc_wifi_hotspot_dialog_set_hostname   (CcWifiHotspotDialog *self,
+                                                            const gchar         *host_name);
+void                 cc_wifi_hotspot_dialog_set_device     (CcWifiHotspotDialog *self,
+                                                            NMDeviceWifi        *device);
+NMConnection        *cc_wifi_hotspot_dialog_get_connection (CcWifiHotspotDialog *self);
+void                 cc_wifi_hotspot_dialog_set_connection (CcWifiHotspotDialog *self,
+                                                            NMConnection        *connection);
+
+G_END_DECLS
diff --git a/panels/network/cc-wifi-hotspot-dialog.ui b/panels/network/cc-wifi-hotspot-dialog.ui
new file mode 100644
index 000000000..f062ad5ff
--- /dev/null
+++ b/panels/network/cc-wifi-hotspot-dialog.ui
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="CcWifiHotspotDialog" parent="GtkMessageDialog">
+    <property name="modal">1</property>
+    <property name="destroy-with-parent">1</property>
+    <property name="text" translatable="yes" comments="Translate the text only">&lt;big&gt;&lt;b&gt;Turn On 
Wi-Fi Hotspot?&lt;/b&gt;&lt;/big&gt;</property>
+    <property name="use-markup">1</property>
+    <property name="message-type">other</property>
+    <signal name="delete-event" handler="gtk_widget_hide_on_delete"/>
+
+    <child internal-child="message_area">
+      <object class="GtkBox">
+        <property name="visible">1</property>
+        <property name="margin-top">0</property>
+
+        <child>
+          <object class="GtkLabel" id="label">
+            <property name="visible">1</property>
+            <property name="wrap">1</property>
+            <property name="max-width-chars">50</property>
+            <property name="label" translatable="yes">Wi-Fi hotspot allows others to share your internet 
connection, by creating a Wi-Fi network that they can connect to. To do this, you must have an internet 
connection through a source other than Wi-Fi.</property>
+            <property name="xalign">0.0</property>
+          </object>
+        </child>
+
+        <child>
+          <object class="GtkLabel" id="connection_label">
+            <property name="visible">1</property>
+            <property name="margin-bottom">18</property>
+            <property name="wrap">1</property>
+            <property name="max-width-chars">40</property>
+            <property name="use-markup">1</property>
+            <property name="xalign">0.0</property>
+          </object>
+        </child>
+
+        <child>
+          <object class="GtkGrid">
+            <property name="visible">1</property>
+            <property name="row-spacing">6</property>
+            <property name="column-spacing">12</property>
+
+            <!-- Hotspot SSID Name -->
+            <child>
+              <object class="GtkLabel">
+                <property name="label" translatable="yes">Network Name</property>
+                <property name="halign">end</property>
+                <property name="visible">1</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="name_entry">
+                <property name="visible">1</property>
+                <property name="hexpand">1</property>
+                <property name="max-length">64</property>
+                <signal name="changed" handler="hotspot_entry_changed_cb" swapped="yes" />
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+
+            <!-- Hotspot Password -->
+            <child>
+              <object class="GtkLabel">
+                <property name="label" translatable="yes">Password</property>
+                <property name="halign">end</property>
+                <property name="visible">1</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="password_entry">
+                <property name="visible">1</property>
+                <property name="max-length">64</property>
+                <property name="secondary-icon-name">view-refresh-symbolic</property>
+                <property name="secondary-icon-tooltip-text" translatable="yes">Generate Random 
Password</property>
+                <property name="placeholder-text" translatable="yes">Autogenerate Password</property>
+                <signal name="icon-press" handler="generate_password_clicked_cb" swapped="yes" />
+                <signal name="changed" handler="hotspot_entry_changed_cb" swapped="yes" />
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+
+            <!-- Error Label -->
+            <child>
+              <object class="GtkLabel" id="error_label">
+                <property name="halign">start</property>
+                <property name="visible">1</property>
+                <style>
+                  <class name="dim-label" />
+                </style>
+                <attributes>
+                  <attribute name="scale" value="0.83"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+
+          </object>
+        </child>
+
+      </object>
+    </child>
+
+    <child type="action">
+      <object class="GtkButton" id="cancel_button">
+        <property name="visible">1</property>
+        <property name="use-underline">1</property>
+        <property name="label" translatable="yes">_Cancel</property>
+      </object>
+    </child>
+    <child type="action">
+      <object class="GtkButton" id="ok_button">
+        <property name="visible">1</property>
+        <property name="can-default">1</property>
+        <property name="use-underline">1</property>
+        <property name="label" translatable="yes">_Turn On</property>
+      </object>
+    </child>
+
+    <action-widgets>
+      <action-widget response="cancel">cancel_button</action-widget>
+      <action-widget response="apply" default="true">ok_button</action-widget>
+    </action-widgets>
+  </template>
+</interface>
diff --git a/panels/network/meson.build b/panels/network/meson.build
index 576fdd3c3..18582f6c3 100644
--- a/panels/network/meson.build
+++ b/panels/network/meson.build
@@ -38,6 +38,7 @@ sources = files(
   'cc-wifi-connection-row.c',
   'cc-wifi-connection-list.c',
   'cc-wifi-panel.c',
+  'cc-wifi-hotspot-dialog.c',
   'net-device.c',
   'net-device-ethernet.c',
   'net-device-mobile.c',
@@ -54,6 +55,7 @@ resource_data = files(
   'cc-network-panel.ui',
   'cc-wifi-connection-row.ui',
   'cc-wifi-panel.ui',
+  'cc-wifi-hotspot-dialog.ui',
   'network-ethernet.ui',
   'network-mobile.ui',
   'network-proxy.ui',
@@ -78,4 +80,4 @@ network_panel_lib = static_library(
   c_args: cflags,
   link_with: libconnection_editor
 )
-panels_libs += network_panel_lib
\ No newline at end of file
+panels_libs += network_panel_lib
diff --git a/panels/network/net-device-wifi.c b/panels/network/net-device-wifi.c
index d66492a94..9efed8cc6 100644
--- a/panels/network/net-device-wifi.c
+++ b/panels/network/net-device-wifi.c
@@ -32,6 +32,7 @@
 #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"
@@ -64,6 +65,7 @@ struct _NetDeviceWifi
         gchar                   *selected_ssid_title;
         gchar                   *selected_connection_id;
         gchar                   *selected_ap_id;
+        CcWifiHotspotDialog     *hotspot_dialog;
 
         gint64                   last_scan;
         gboolean                 scanning;
@@ -797,71 +799,6 @@ get_hostname (void)
         return g_variant_dup_string (inner, NULL);
 }
 
-static GBytes *
-generate_ssid_for_hotspot (NetDeviceWifi *device_wifi)
-{
-        GBytes *ssid_bytes;
-        g_autofree gchar *hostname = NULL;
-        gchar *ssid;
-
-        hostname = get_hostname ();
-        ssid = pretty_hostname_to_ssid (hostname);
-
-        ssid_bytes = g_bytes_new_with_free_func (ssid,
-                                                 strlen (ssid),
-                                                 g_free,
-                                                 NULL);
-
-        return ssid_bytes;
-}
-
-#define WPA_PASSKEY_SIZE 8
-static void
-set_wpa_key (NMSettingWirelessSecurity *sws)
-{
-        /* generate a 8-chars ASCII WPA key */
-        char key[WPA_PASSKEY_SIZE + 1];
-        guint i;
-
-        for (i = 0; i < WPA_PASSKEY_SIZE; i++) {
-                gint c;
-                c = g_random_int_range (33, 126);
-                /* too many non alphanumeric characters are hard to remember for humans */
-                while (!g_ascii_isalnum (c))
-                        c = g_random_int_range (33, 126);
-
-                key[i] = (gchar) c;
-        }
-        key[WPA_PASSKEY_SIZE] = '\0';
-
-        g_object_set (sws,
-                      "key-mgmt", "wpa-psk",
-                      "psk", key,
-                      NULL);
-}
-
-static void
-set_wep_key (NMSettingWirelessSecurity *sws)
-{
-        gchar key[11];
-        gint i;
-        const gchar *hexdigits = "0123456789abcdef";
-
-        /* generate a 10-digit hex WEP key */
-        for (i = 0; i < 10; i++) {
-                gint digit;
-                digit = g_random_int_range (0, 16);
-                key[i] = hexdigits[digit];
-        }
-        key[10] = 0;
-
-        g_object_set (sws,
-                      "key-mgmt", "none",
-                      "wep-key0", key,
-                      "wep-key-type", NM_WEP_KEY_TYPE_KEY,
-                      NULL);
-}
-
 static gboolean
 is_hotspot_connection (NMConnection *connection)
 {
@@ -1002,228 +939,59 @@ overwrite_ssid_cb (GObject      *source_object,
                                              device_wifi);
 }
 
-static void
-start_shared_connection (NetDeviceWifi *device_wifi)
-{
-        NMConnection *hotspot_connection;
-        g_autoptr(NMConnection) c = NULL;
-        NMSettingConnection *sc;
-        NMSettingWireless *sw;
-        NMSettingIP4Config *sip;
-        NMSettingWirelessSecurity *sws;
-        NMDevice *device;
-        g_autoptr(GBytes) ssid = NULL;
-        const gchar *str_mac;
-        struct ether_addr *bin_mac;
-        NMClient *client;
-        const char *mode;
-        NMDeviceWifiCapabilities caps;
-        GCancellable *cancellable;
-
-        device = net_device_get_nm_device (NET_DEVICE (device_wifi));
-        g_assert (nm_device_get_device_type (device) == NM_DEVICE_TYPE_WIFI);
-
-        hotspot_connection = net_device_wifi_get_hotspot_connection (device_wifi);
-
-        ssid = generate_ssid_for_hotspot (device_wifi);
-
-        client = net_object_get_client (NET_OBJECT (device_wifi));
-        cancellable = net_object_get_cancellable (NET_OBJECT (device_wifi));
-        if (hotspot_connection != NULL) {
-                NMSettingWireless *sw;
-                const char *c_path;
-                NMRemoteConnection *connection;
-
-                sw = nm_connection_get_setting_wireless (hotspot_connection);
-                g_object_set (sw, "ssid", ssid, NULL);
-
-                c_path = nm_connection_get_path (hotspot_connection);
-                connection = nm_client_get_connection_by_path (client, c_path);
-
-                g_debug ("overwriting ssid to %s", (char *) g_bytes_get_data (ssid, NULL));
-
-                nm_remote_connection_commit_changes_async (connection,
-                                                           TRUE,
-                                                           cancellable,
-                                                           overwrite_ssid_cb,
-                                                           device_wifi);
-                return;
-        }
-
-        g_debug ("create new hotspot connection with SSID '%s'",
-                 (char *) g_bytes_get_data (ssid, NULL));
-        c = nm_simple_connection_new ();
-
-        sc = (NMSettingConnection *)nm_setting_connection_new ();
-        g_object_set (sc,
-                      "type", "802-11-wireless",
-                      "id", "Hotspot",
-                      "autoconnect", FALSE,
-                      NULL);
-        nm_connection_add_setting (c, (NMSetting *)sc);
-
-        sw = (NMSettingWireless *)nm_setting_wireless_new ();
-
-       /* Use real AP mode if the device supports it */
-        caps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (device));
-        if (caps & NM_WIFI_DEVICE_CAP_AP)
-               mode = NM_SETTING_WIRELESS_MODE_AP;
-        else
-                mode = NM_SETTING_WIRELESS_MODE_ADHOC;
-
-        g_object_set (sw,
-                      "mode", mode,
-                      NULL);
-
-        str_mac = nm_device_wifi_get_permanent_hw_address (NM_DEVICE_WIFI (device));
-        bin_mac = ether_aton (str_mac);
-        if (bin_mac) {
-                g_autoptr(GByteArray) hw_address = NULL;
-
-                hw_address = g_byte_array_sized_new (ETH_ALEN);
-                g_byte_array_append (hw_address, bin_mac->ether_addr_octet, ETH_ALEN);
-                g_object_set (sw,
-                              "mac-address", hw_address,
-                              NULL);
-        }
-        nm_connection_add_setting (c, (NMSetting *)sw);
-
-        sip = (NMSettingIP4Config*) nm_setting_ip4_config_new ();
-        g_object_set (sip, "method", "shared", NULL);
-        nm_connection_add_setting (c, (NMSetting *)sip);
-
-        g_object_set (sw, "ssid", ssid, NULL);
-
-        sws = (NMSettingWirelessSecurity*) nm_setting_wireless_security_new ();
-
-        if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0) {
-                if (caps & NM_WIFI_DEVICE_CAP_RSN) {
-                        set_wpa_key (sws);
-                        nm_setting_wireless_security_add_proto (sws, "rsn");
-                        nm_setting_wireless_security_add_pairwise (sws, "ccmp");
-                        nm_setting_wireless_security_add_group (sws, "ccmp");
-                } else if (caps & NM_WIFI_DEVICE_CAP_WPA) {
-                        set_wpa_key (sws);
-                        nm_setting_wireless_security_add_proto (sws, "wpa");
-                        nm_setting_wireless_security_add_pairwise (sws, "tkip");
-                        nm_setting_wireless_security_add_group (sws, "tkip");
-                } else {
-                        set_wep_key (sws);
-                }
-        } else {
-                set_wep_key (sws);
-        }
-
-        nm_connection_add_setting (c, (NMSetting *)sws);
-
-        nm_client_add_and_activate_connection_async (client,
-                                                     c,
-                                                     device,
-                                                     NULL,
-                                                     cancellable,
-                                                     activate_new_cb,
-                                                     device_wifi);
-}
-
-static void
-start_hotspot_response_cb (GtkWidget *dialog, gint response, NetDeviceWifi *device_wifi)
-{
-        if (response == GTK_RESPONSE_OK) {
-                start_shared_connection (device_wifi);
-        }
-        gtk_widget_destroy (dialog);
-}
-
 static void
 start_hotspot (GtkButton *button, NetDeviceWifi *device_wifi)
 {
         NMDevice *device;
-        const GPtrArray *connections;
         g_autofree gchar *active_ssid = NULL;
         NMClient *client;
-        GtkWidget *dialog;
         GtkWidget *window;
-        GtkWidget *message_area;
-        GtkWidget *label;
-        GString *str;
+        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));
-        connections = nm_client_get_active_connections (client);
-        if (connections) {
-                gint i;
-                for (i = 0; i < connections->len; i++) {
-                        NMActiveConnection *c;
-                        const GPtrArray *devices;
-                        c = (NMActiveConnection *)connections->pdata[i];
-                        devices = nm_active_connection_get_devices (c);
-                        if (devices && devices->pdata[0] == device) {
-                                NMAccessPoint *ap;
-                                GBytes *ssid;
-                                ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (device));
-                                ssid = nm_access_point_get_ssid (ap);
-                                active_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), 
g_bytes_get_size (ssid));
-                                break;
-                        }
-                }
-        }
 
         window = gtk_widget_get_toplevel (GTK_WIDGET (button));
 
-        str = g_string_new ("");
-
-        if (active_ssid) {
-                g_string_append_printf (str, _("Switching on the wireless hotspot will disconnect you from 
<b>%s</b>."), active_ssid);
-                g_string_append (str, " ");
+        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);
         }
 
-        g_string_append (str, _("It is not possible to access the Internet through your wireless while the 
hotspot is active."));
-
-        dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (window),
-                                                     GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                                                     GTK_MESSAGE_OTHER,
-                                                     GTK_BUTTONS_NONE,
-                                                     "<big><b>%s</b></big>",
-                                                     _("Turn On Wi-Fi Hotspot?"));
-
-        /* Because we can't control the text alignment with markup, add
-         * the strings as labels directly */
-        message_area = gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (dialog));
-
-        label = g_object_new (GTK_TYPE_LABEL,
-                              "use-markup", TRUE,
-                              "xalign", 0.5,
-                              "max-width-chars", 50,
-                              "wrap", TRUE,
-                              "label", str->str,
-                              "justify", GTK_JUSTIFY_CENTER,
-                              "halign", GTK_ALIGN_CENTER,
-                              NULL);
-        gtk_container_add (GTK_CONTAINER (message_area), label);
-
-        label = g_object_new (GTK_TYPE_LABEL,
-                              "use-markup", TRUE,
-                              "xalign", 0.5,
-                              "max-width-chars", 50,
-                              "wrap", TRUE,
-                              "label", _("Wi-Fi hotspots are usually used to share an additional Internet 
connection over Wi-Fi."),
-                              "justify", GTK_JUSTIFY_CENTER,
-                              "halign", GTK_ALIGN_CENTER,
-                              NULL);
-        gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
-        gtk_container_add (GTK_CONTAINER (message_area), label);
-
-        gtk_widget_show_all (message_area);
-
-        gtk_dialog_add_buttons (GTK_DIALOG (dialog),
-                                _("_Cancel"), GTK_RESPONSE_CANCEL,
-                                _("_Turn On"), GTK_RESPONSE_OK,
-                                NULL);
-        g_signal_connect (dialog, "response",
-                          G_CALLBACK (start_hotspot_response_cb), device_wifi);
-
-        gtk_window_present (GTK_WINDOW (dialog));
-        g_string_free (str, TRUE);
+        gtk_widget_hide (GTK_WIDGET (device_wifi->hotspot_dialog));
 }
 
 static void
diff --git a/panels/network/network.gresource.xml b/panels/network/network.gresource.xml
index a3691b1a9..0fc1651e1 100644
--- a/panels/network/network.gresource.xml
+++ b/panels/network/network.gresource.xml
@@ -4,6 +4,7 @@
     <!-- Network panel -->
     <file preprocess="xml-stripblanks">cc-network-panel.ui</file>
     <file preprocess="xml-stripblanks">cc-wifi-connection-row.ui</file>
+    <file preprocess="xml-stripblanks">cc-wifi-hotspot-dialog.ui</file>
     <file preprocess="xml-stripblanks">network-proxy.ui</file>
     <file preprocess="xml-stripblanks">network-vpn.ui</file>
     <file preprocess="xml-stripblanks">network-wifi.ui</file>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]