Blob Blame History Raw
diff --git a/data/Makefile.am b/data/Makefile.am
index cdf9dc5..8800ad8 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -22,6 +22,9 @@ GTKRC_FILES =		\
 xsessionsdir = $(datadir)/xsessions
 xsessions_DATA = sugar.desktop
 
+nmservicedir = $(sysconfdir)/dbus-1/system.d/
+nmservice_DATA = nm-user-settings.conf
+
 mime_xml_in_files = sugar.xml.in
 mime_xml_files = $(mime_xml_in_files:.xml.in=.xml)
 @INTLTOOL_XML_RULE@
@@ -43,5 +46,5 @@ if ENABLE_UPDATE_MIMEDB
 	fi
 endif
 
-EXTRA_DIST = $(sugar_DATA) $(xsessions_DATA) $(mime_xml_in_files) em.py gtkrc.em
+EXTRA_DIST = $(sugar_DATA) $(xsessions_DATA) $(nmservice_DATA) $(mime_xml_in_files) em.py gtkrc.em
 CLEANFILES = $(GTKRC_FILES) $(mime_xml_files)
diff --git a/data/nm-user-settings.conf b/data/nm-user-settings.conf
new file mode 100644
index 0000000..af7c642
--- /dev/null
+++ b/data/nm-user-settings.conf
@@ -0,0 +1,34 @@
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+	<policy user="root">
+		<allow own="org.freedesktop.NetworkManagerUserSettings"/>
+
+		<allow send_destination="org.freedesktop.NetworkManagerUserSettings"/>
+		<allow send_interface="org.freedesktop.NetworkManagerSettings"/>
+
+		<!-- Only root can get secrets -->
+		<allow send_interface="org.freedesktop.NetworkManagerSettings.Secrets"/>
+	</policy>
+	<policy at_console="true">
+		<allow own="org.freedesktop.NetworkManagerUserSettings"/>
+
+		<allow send_destination="org.freedesktop.NetworkManagerUserSettings"/>
+		<allow send_interface="org.freedesktop.NetworkManagerSettings"/>
+
+		<!-- Only root can get secrets -->
+		<deny send_interface="org.freedesktop.NetworkManagerSettings.Secrets"/>
+	</policy>
+	<policy context="default">
+		<deny own="org.freedesktop.NetworkManagerUserSettings"/>
+
+		<allow send_destination="org.freedesktop.NetworkManagerUserSettings"/>
+		<allow send_interface="org.freedesktop.NetworkManagerSettings"/>
+		<!-- Only root can get secrets -->
+		<deny send_interface="org.freedesktop.NetworkManagerSettings.Secrets"/>
+	</policy>
+
+	<limit name="max_replies_per_connection">512</limit>
+</busconfig>
+
diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am
index 8cd9c77..f589d42 100644
--- a/src/hardware/Makefile.am
+++ b/src/hardware/Makefile.am
@@ -2,12 +2,4 @@ sugardir = $(pkgdatadir)/shell/hardware
 sugar_PYTHON =				\
 	__init__.py			\
 	hardwaremanager.py		\
-	keydialog.py			\
-	nmclient.py			\
-	nminfo.py			\
 	schoolserver.py
-
-dbusservicedir = $(sysconfdir)/dbus-1/system.d/
-dbusservice_DATA = NetworkManagerInfo.conf
-
-EXTRA_DIST = $(dbusservice_DATA)
diff --git a/src/hardware/NetworkManagerInfo.conf b/src/hardware/NetworkManagerInfo.conf
deleted file mode 100644
index 4fb8270..0000000
--- a/src/hardware/NetworkManagerInfo.conf
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE busconfig PUBLIC
- "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-<busconfig>
-	<policy user="root">
-		<allow own="org.freedesktop.NetworkManagerInfo"/>
-
-		<allow send_destination="org.freedesktop.NetworkManagerInfo"/>
-                <allow send_interface="org.freedesktop.NetworkManagerInfo"/>
-	</policy>
-	<policy at_console="true">
-		<allow own="org.freedesktop.NetworkManagerInfo"/>
-
-		<allow send_destination="org.freedesktop.NetworkManagerInfo"/>
-                <allow send_interface="org.freedesktop.NetworkManagerInfo"/>
-	</policy>
-	<policy context="default">
-		<deny own="org.freedesktop.NetworkManagerInfo"/>
-
-		<deny send_destination="org.freedesktop.NetworkManagerInfo"/>
-		<deny send_interface="org.freedesktop.NetworkManagerInfo"/>
-	</policy>
-
-        <limit name="max_replies_per_connection">512</limit>
-</busconfig>
-
diff --git a/src/hardware/hardwaremanager.py b/src/hardware/hardwaremanager.py
index c4f9f75..2e5a16b 100644
--- a/src/hardware/hardwaremanager.py
+++ b/src/hardware/hardwaremanager.py
@@ -19,7 +19,6 @@ import logging
 import dbus
 import gobject
 
-from hardware.nmclient import NMClient
 from sugar.profile import get_profile
 from sugar import env
 from sugar import _sugarext
@@ -111,13 +110,5 @@ class HardwareManager(gobject.GObject):
 def get_manager():
     return _manager
 
-def get_network_manager():
-    return _network_manager
-
 _manager = HardwareManager()
 
-try:
-    _network_manager = NMClient()
-except dbus.DBusException, e:
-    _network_manager = None
-    logging.info('Network manager service not found.')
diff --git a/src/hardware/keydialog.py b/src/hardware/keydialog.py
deleted file mode 100644
index 88a551f..0000000
--- a/src/hardware/keydialog.py
+++ /dev/null
@@ -1,354 +0,0 @@
-# vi: ts=4 ai noet
-#
-# Copyright (C) 2006-2007 Red Hat, Inc.
-#
-# 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 St, Fifth Floor, Boston, MA  02110-1301  USA
-
-import md5
-from gettext import gettext as _
-
-import gtk
-
-IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001
-IW_AUTH_ALG_SHARED_KEY  = 0x00000002
-
-IW_AUTH_WPA_VERSION_DISABLED = 0x00000001
-IW_AUTH_WPA_VERSION_WPA      = 0x00000002
-IW_AUTH_WPA_VERSION_WPA2     = 0x00000004
-
-NM_802_11_CAP_NONE            = 0x00000000
-NM_802_11_CAP_PROTO_NONE      = 0x00000001
-NM_802_11_CAP_PROTO_WEP       = 0x00000002
-NM_802_11_CAP_PROTO_WPA       = 0x00000004
-NM_802_11_CAP_PROTO_WPA2      = 0x00000008
-NM_802_11_CAP_KEY_MGMT_PSK    = 0x00000040
-NM_802_11_CAP_KEY_MGMT_802_1X = 0x00000080
-NM_802_11_CAP_CIPHER_WEP40    = 0x00001000
-NM_802_11_CAP_CIPHER_WEP104   = 0x00002000
-NM_802_11_CAP_CIPHER_TKIP     = 0x00004000
-NM_802_11_CAP_CIPHER_CCMP     = 0x00008000
-
-NM_AUTH_TYPE_WPA_PSK_AUTO = 0x00000000
-IW_AUTH_CIPHER_NONE   = 0x00000001
-IW_AUTH_CIPHER_WEP40  = 0x00000002
-IW_AUTH_CIPHER_TKIP   = 0x00000004
-IW_AUTH_CIPHER_CCMP   = 0x00000008
-IW_AUTH_CIPHER_WEP104 = 0x00000010
-
-IW_AUTH_KEY_MGMT_802_1X = 0x1
-IW_AUTH_KEY_MGMT_PSK    = 0x2
-
-def string_is_hex(key):
-    is_hex = True
-    for c in key:
-        if not 'a' <= c.lower() <= 'f' and not '0' <= c <= '9':
-            is_hex = False
-    return is_hex
-
-def string_is_ascii(string):
-    try:
-        string.encode('ascii')
-        return True
-    except UnicodeEncodeError:
-        return False
-
-def string_to_hex(passphrase):
-    key = ''
-    for c in passphrase:
-        key += '%02x' % ord(c)
-    return key
-
-def hash_passphrase(passphrase):
-    # passphrase must have a length of 64
-    if len(passphrase) > 64:
-        passphrase = passphrase[:64]
-    elif len(passphrase) < 64:
-        while len(passphrase) < 64:
-            passphrase += passphrase[:64 - len(passphrase)]
-    passphrase = md5.new(passphrase).digest()
-    return string_to_hex(passphrase)[:26]
-
-class KeyDialog(gtk.Dialog):
-    def __init__(self, net, async_cb, async_err_cb):
-        gtk.Dialog.__init__(self, flags=gtk.DIALOG_MODAL)
-        self.set_title("Wireless Key Required")
-
-        self._net = net
-        self._async_cb = async_cb
-        self._async_err_cb = async_err_cb
-        self._entry = None
-
-        self.set_has_separator(False)        
-
-        label = gtk.Label("A wireless encryption key is required for\n" \
-                          " the wireless network '%s'." % net.get_ssid())
-        self.vbox.pack_start(label)
-
-        self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
-                         gtk.STOCK_OK, gtk.RESPONSE_OK)
-        self.set_default_response(gtk.RESPONSE_OK)
-        self.set_has_separator(True)
-
-    def add_key_entry(self):
-        self._entry = gtk.Entry()
-        #self._entry.props.visibility = False
-        self._entry.connect('changed', self._update_response_sensitivity)
-        self._entry.connect('activate', self._entry_activate_cb)
-        self.vbox.pack_start(self._entry)
-        self.vbox.set_spacing(6)
-        self.vbox.show_all()
-
-        self._update_response_sensitivity()
-        self._entry.grab_focus()
-
-    def _entry_activate_cb(self, entry):
-        self.response(gtk.RESPONSE_OK)
-
-    def create_security(self):
-        raise NotImplementedError
-
-    def get_network(self):
-        return self._net
-
-    def get_callbacks(self):
-        return (self._async_cb, self._async_err_cb)
-
-WEP_PASSPHRASE = 1
-WEP_HEX = 2
-WEP_ASCII = 3
-
-class WEPKeyDialog(KeyDialog):
-    def __init__(self, net, async_cb, async_err_cb):
-        KeyDialog.__init__(self, net, async_cb, async_err_cb)
-
-        # WEP key type
-        self.key_store = gtk.ListStore(str, int)
-        self.key_store.append(["Passphrase (128-bit)", WEP_PASSPHRASE])
-        self.key_store.append(["Hex (40/128-bit)", WEP_HEX])
-        self.key_store.append(["ASCII (40/128-bit)", WEP_ASCII])
-
-        self.key_combo = gtk.ComboBox(self.key_store)
-        cell = gtk.CellRendererText()
-        self.key_combo.pack_start(cell, True)
-        self.key_combo.add_attribute(cell, 'text', 0)
-        self.key_combo.set_active(0)
-        self.key_combo.connect('changed', self._key_combo_changed_cb)
-
-        hbox = gtk.HBox()
-        hbox.pack_start(gtk.Label(_("Key Type:")))
-        hbox.pack_start(self.key_combo)
-        hbox.show_all()
-        self.vbox.pack_start(hbox)
-
-        # Key entry field
-        self.add_key_entry()
-
-        # WEP authentication mode
-        self.auth_store = gtk.ListStore(str, int)
-        self.auth_store.append(["Open System", IW_AUTH_ALG_OPEN_SYSTEM])
-        self.auth_store.append(["Shared Key", IW_AUTH_ALG_SHARED_KEY])
-
-        self.auth_combo = gtk.ComboBox(self.auth_store)
-        cell = gtk.CellRendererText()
-        self.auth_combo.pack_start(cell, True)
-        self.auth_combo.add_attribute(cell, 'text', 0)
-        self.auth_combo.set_active(0)
-
-        hbox = gtk.HBox()
-        hbox.pack_start(gtk.Label(_("Authentication Type:")))
-        hbox.pack_start(self.auth_combo)
-        hbox.show_all()
-
-        self.vbox.pack_start(hbox)
-
-    def _key_combo_changed_cb(self, widget):
-        self._update_response_sensitivity()
-
-    def _get_security(self):
-        key = self._entry.get_text()
-
-        it = self.key_combo.get_active_iter()
-        (key_type, ) = self.key_store.get(it, 1)
-
-        if key_type == WEP_PASSPHRASE:
-            key = hash_passphrase(key)
-        elif key_type == WEP_ASCII:
-            key = string_to_hex(key)
-
-        it = self.auth_combo.get_active_iter()
-        (auth_alg, ) = self.auth_store.get(it, 1)
-
-        we_cipher = None
-        if len(key) == 26:
-            we_cipher = IW_AUTH_CIPHER_WEP104
-        elif len(key) == 10:
-            we_cipher = IW_AUTH_CIPHER_WEP40
-
-        return (we_cipher, key, auth_alg)
-
-    def print_security(self):
-        (we_cipher, key, auth_alg) = self._get_security()
-        print "Cipher: %d" % we_cipher
-        print "Key: %s" % key
-        print "Auth: %d" % auth_alg
-
-    def create_security(self):
-        (we_cipher, key, auth_alg) = self._get_security()
-        from nminfo import Security
-        return Security.new_from_args(we_cipher, (key, auth_alg))
-
-    def _update_response_sensitivity(self, ignored=None):
-        key = self._entry.get_text()
-        it = self.key_combo.get_active_iter()
-        (key_type, ) = self.key_store.get(it, 1)
-
-        valid = False
-        if key_type == WEP_PASSPHRASE:
-            # As the md5 passphrase can be of any length and has no indicator,
-            # we cannot check for the validity of the input.
-            if len(key) > 0:
-                valid = True
-        elif key_type == WEP_ASCII:
-            if len(key) == 5 or len(key) == 13:
-                valid = string_is_ascii(key)
-        elif key_type == WEP_HEX:
-            if len(key) == 10 or len(key) == 26:
-                valid = string_is_hex(key)
-
-        self.set_response_sensitive(gtk.RESPONSE_OK, valid)
-
-class WPAKeyDialog(KeyDialog):
-    def __init__(self, net, async_cb, async_err_cb):
-        KeyDialog.__init__(self, net, async_cb, async_err_cb)
-        self.add_key_entry()
-
-        self.store = gtk.ListStore(str, int)
-        self.store.append(["Automatic", NM_AUTH_TYPE_WPA_PSK_AUTO])
-        if net.get_caps() & NM_802_11_CAP_CIPHER_CCMP:
-            self.store.append(["AES-CCMP", IW_AUTH_CIPHER_CCMP])
-        if net.get_caps() & NM_802_11_CAP_CIPHER_TKIP:
-            self.store.append(["TKIP", IW_AUTH_CIPHER_TKIP])
-
-        self.combo = gtk.ComboBox(self.store)
-        cell = gtk.CellRendererText()
-        self.combo.pack_start(cell, True)
-        self.combo.add_attribute(cell, 'text', 0)
-        self.combo.set_active(0)
-
-        self.hbox = gtk.HBox()
-        self.hbox.pack_start(gtk.Label(_("Encryption Type:")))
-        self.hbox.pack_start(self.combo)
-        self.hbox.show_all()
-
-        self.vbox.pack_start(self.hbox)
-
-    def _get_security(self):
-        ssid = self.get_network().get_ssid()
-        key = self._entry.get_text()
-        is_hex = string_is_hex(key)
-
-        real_key = None
-        if len(key) == 64 and is_hex:
-            # Hex key
-            real_key = key
-        elif len(key) >= 8 and len(key) <= 63:
-            # passphrase
-            from subprocess import Popen, PIPE
-            p = Popen(['/usr/sbin/wpa_passphrase', ssid, key], stdout=PIPE)
-            for line in p.stdout:
-                if line.strip().startswith("psk="):
-                    real_key = line.strip()[4:]
-            if p.wait() != 0:
-                raise RuntimeError("Error hashing passphrase")
-            if real_key and len(real_key) != 64:
-                real_key = None
-
-        if not real_key:
-            raise RuntimeError("Invalid key")
-
-        it = self.combo.get_active_iter()
-        (we_cipher, ) = self.store.get(it, 1)
-
-        wpa_ver = IW_AUTH_WPA_VERSION_WPA
-        caps = self.get_network().get_caps()
-        if caps & NM_802_11_CAP_PROTO_WPA2:
-            wpa_ver = IW_AUTH_WPA_VERSION_WPA2
-
-        return (we_cipher, real_key, wpa_ver)
-
-    def print_security(self):
-        (we_cipher, key, wpa_ver) = self._get_security()
-        print "Cipher: %d" % we_cipher
-        print "Key: %s" % key
-        print "WPA Ver: %d" % wpa_ver
-
-    def create_security(self):
-        (we_cipher, key, wpa_ver) = self._get_security()
-        from nminfo import Security
-        return Security.new_from_args(we_cipher,
-                                      (key, wpa_ver, IW_AUTH_KEY_MGMT_PSK))
-
-    def _update_response_sensitivity(self, ignored=None):
-        key = self._entry.get_text()
-        is_hex = string_is_hex(key)
-
-        valid = False
-        if len(key) == 64 and is_hex:
-            # hex key
-            valid = True
-        elif len(key) >= 8 and len(key) <= 63:
-            # passphrase
-            valid = True
-        self.set_response_sensitive(gtk.RESPONSE_OK, valid)
-        return False
-
-def new_key_dialog(net, async_cb, async_err_cb):
-    caps = net.get_caps()
-    if (caps & NM_802_11_CAP_CIPHER_TKIP or caps & NM_802_11_CAP_CIPHER_CCMP) \
-            and (caps & NM_802_11_CAP_PROTO_WPA or \
-                caps & NM_802_11_CAP_PROTO_WPA2):
-        return WPAKeyDialog(net, async_cb, async_err_cb)
-    elif (caps & NM_802_11_CAP_CIPHER_WEP40 or \
-            caps & NM_802_11_CAP_CIPHER_WEP104) and \
-            (caps & NM_802_11_CAP_PROTO_WEP):
-        return WEPKeyDialog(net, async_cb, async_err_cb)
-    else:
-        raise RuntimeError("Unhandled network capabilities %x" % caps)
-
-
-
-class FakeNet(object):
-    def get_ssid(self):
-        return "olpcwpa"
-
-    def get_caps(self):
-        return NM_802_11_CAP_CIPHER_CCMP | NM_802_11_CAP_CIPHER_TKIP | \
-                NM_802_11_CAP_PROTO_WPA
-
-def response_cb(widget, response_id):
-    if response_id == gtk.RESPONSE_OK:
-        print dialog.print_security()
-    else:
-        print "canceled"
-    widget.hide()
-    widget.destroy()
-
-
-if __name__ == "__main__":
-    fake_net = FakeNet()
-    dialog = new_key_dialog(fake_net, None, None)
-    dialog.connect("response", response_cb)
-    dialog.run()
-
diff --git a/src/hardware/nmclient.py b/src/hardware/nmclient.py
deleted file mode 100644
index c517391..0000000
--- a/src/hardware/nmclient.py
+++ /dev/null
@@ -1,795 +0,0 @@
-#
-# Copyright (C) 2006-2007 Red Hat, Inc.
-#
-# 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 St, Fifth Floor, Boston, MA  02110-1301  USA
-
-import logging
-
-import dbus
-import dbus.glib
-import dbus.decorators
-import gobject
-
-from hardware import nminfo
-from sugar.graphics import xocolor
-
-IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001
-IW_AUTH_ALG_SHARED_KEY  = 0x00000002
-
-NM_DEVICE_STAGE_STRINGS = ("Unknown",
-                           "Prepare",
-                           "Config",
-                           "Need Users Key",
-                           "IP Config",
-                           "IP Config Get",
-                           "IP Config Commit",
-                           "Activated",
-                           "Failed",
-                           "Canceled"
-                           )
-
-NM_SERVICE = 'org.freedesktop.NetworkManager'
-NM_IFACE = 'org.freedesktop.NetworkManager'
-NM_IFACE_DEVICES = 'org.freedesktop.NetworkManager.Devices'
-NM_PATH = '/org/freedesktop/NetworkManager'
-
-DEVICE_TYPE_UNKNOWN = 0
-DEVICE_TYPE_802_3_ETHERNET = 1
-DEVICE_TYPE_802_11_WIRELESS = 2
-DEVICE_TYPE_802_11_MESH_OLPC = 3
-
-NM_DEVICE_CAP_NONE = 0x00000000
-NM_DEVICE_CAP_NM_SUPPORTED = 0x00000001
-NM_DEVICE_CAP_CARRIER_DETECT = 0x00000002
-NM_DEVICE_CAP_WIRELESS_SCAN = 0x00000004
-
-sys_bus = dbus.SystemBus()
-
-NM_802_11_CAP_NONE            = 0x00000000
-NM_802_11_CAP_PROTO_NONE      = 0x00000001
-NM_802_11_CAP_PROTO_WEP       = 0x00000002
-NM_802_11_CAP_PROTO_WPA       = 0x00000004
-NM_802_11_CAP_PROTO_WPA2      = 0x00000008
-NM_802_11_CAP_KEY_MGMT_PSK    = 0x00000040
-NM_802_11_CAP_KEY_MGMT_802_1X = 0x00000080
-NM_802_11_CAP_CIPHER_WEP40    = 0x00001000
-NM_802_11_CAP_CIPHER_WEP104   = 0x00002000
-NM_802_11_CAP_CIPHER_TKIP     = 0x00004000
-NM_802_11_CAP_CIPHER_CCMP     = 0x00008000
-
-NETWORK_STATE_CONNECTING   = 0
-NETWORK_STATE_CONNECTED    = 1
-NETWORK_STATE_NOTCONNECTED = 2
-
-DEVICE_STATE_ACTIVATING = 0
-DEVICE_STATE_ACTIVATED  = 1
-DEVICE_STATE_INACTIVE   = 2
-
-IW_MODE_ADHOC = 1
-IW_MODE_INFRA = 2
-
-class Network(gobject.GObject):
-    __gsignals__ = {
-        'initialized'     : (gobject.SIGNAL_RUN_FIRST,
-                             gobject.TYPE_NONE, ([gobject.TYPE_BOOLEAN])),
-        'strength-changed': (gobject.SIGNAL_RUN_FIRST,
-                             gobject.TYPE_NONE, ([])),
-        'state-changed'   : (gobject.SIGNAL_RUN_FIRST,
-                             gobject.TYPE_NONE, ([]))
-    }
-
-    def __init__(self, client, op):
-        gobject.GObject.__init__(self)
-        self._client = client
-        self._op = op
-        self._ssid = None
-        self._mode = None
-        self._strength = 0
-        self._caps = 0
-        self._valid = False
-        self._favorite = False
-        self._state = NETWORK_STATE_NOTCONNECTED
-
-        obj = sys_bus.get_object(NM_SERVICE, self._op)
-        net = dbus.Interface(obj, NM_IFACE_DEVICES)
-        net.getProperties(reply_handler=self._update_reply_cb,
-                error_handler=self._update_error_cb)
-
-    def _update_reply_cb(self, *props):
-        self._ssid = props[1]
-        self._strength = props[3]
-        self._mode = props[6]
-        self._caps = props[7]
-        if self._caps & NM_802_11_CAP_PROTO_WPA or \
-                self._caps & NM_802_11_CAP_PROTO_WPA2:
-            if not (self._caps & NM_802_11_CAP_KEY_MGMT_PSK):
-                # 802.1x is not supported at this time
-                logging.debug("Net(%s): ssid '%s' dropping because 802.1x" \
-                              "is unsupported" % (self._op, self._ssid))
-                self._valid = False
-                self.emit('initialized', self._valid)
-                return
-        if self._mode != IW_MODE_INFRA:
-            # Don't show Ad-Hoc networks; they usually don't DHCP and therefore
-            # won't work well here.  This also works around the bug where
-            # we show our own mesh SSID on the Mesh view when in mesh mode
-            logging.debug("Net(%s): ssid '%s' is adhoc; not showing" %
-                          (self._op, self._ssid))
-            self._valid = False
-            self.emit('initialized', self._valid)
-            return
-
-        fav_nets = []
-        if self._client.nminfo:
-            fav_nets = self._client.nminfo.get_networks(
-                    nminfo.NETWORK_TYPE_ALLOWED)
-        if self._ssid in fav_nets:
-            self._favorite = True
-
-        self._valid = True
-        logging.debug("Net(%s): caps 0x%X" % (self._ssid, self._caps))
-        self.emit('initialized', self._valid)
-
-    def _update_error_cb(self, err):
-        logging.debug("Net(%s): failed to update. (%s)" % (self._op, err))
-        self._valid = False
-        self.emit('initialized', self._valid)
-
-    def get_colors(self):
-        import sha
-        sh = sha.new()
-        data = self._ssid + hex(self._caps) + hex(self._mode)
-        sh.update(data)
-        h = hash(sh.digest())
-        idx = h % len(xocolor.colors)
-        # stroke, fill
-        return (xocolor.colors[idx][0], xocolor.colors[idx][1])
-
-    def get_ssid(self):
-        return self._ssid
-
-    def get_caps(self):
-        return self._caps
-
-    def get_mode(self):
-        return self._mode
-
-    def get_state(self):
-        return self._state
-
-    def set_state(self, state):
-        if state == self._state:
-            return
-        self._state = state
-        if self._valid:
-            self.emit('state-changed')
-
-    def get_op(self):
-        return self._op
-
-    def get_strength(self):
-        return self._strength
-
-    def set_strength(self, strength):
-        if strength == self._strength:
-            return
-        self._strength = strength
-        if self._valid:
-            self.emit('strength-changed')
-
-    def is_valid(self):
-        return self._valid
-
-    def is_favorite(self):
-        return self._favorite
-
-class Device(gobject.GObject):
-    __gsignals__ = {
-        'initialized':              (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE, ([])),
-        'init-failed':              (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE, ([])),
-        'ssid-changed':             (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE, ([])),
-        'strength-changed':         (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE, ([])),
-        'state-changed':            (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE, ([])),
-        'activation-stage-changed': (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE, ([])),
-        'network-appeared':         (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE,
-                                     ([gobject.TYPE_PYOBJECT])),
-        'network-disappeared':      (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE,
-                                     ([gobject.TYPE_PYOBJECT])),
-        'ip-changed':               (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE, ([])),
-    }
-
-    def __init__(self, client, op):
-        gobject.GObject.__init__(self)
-        self._client = client
-        self._op = op
-        self._iface = None
-        self._type = DEVICE_TYPE_UNKNOWN
-        self._udi = None
-        self._active = False
-        self._act_stage = 0
-        self._strength = 0
-        self._freq = 0.0
-        self._link = False
-        self._valid = False
-        self._networks = {}
-        self._caps = 0
-        self._state = DEVICE_STATE_INACTIVE
-        self._active_network = None
-        self._active_net_sigid = 0
-        self._ip_address = None
-
-        obj = sys_bus.get_object(NM_SERVICE, self._op)
-        self.dev = dbus.Interface(obj, NM_IFACE_DEVICES)
-        self.dev.getProperties(reply_handler=self._update_reply_cb,
-                error_handler=self._update_error_cb)
-
-    def _is_activating(self):
-        if self._active and self._act_stage >= 1 and self._act_stage <= 6:
-            return True
-        return False
-
-    def _is_activated(self):
-        if self._active and self._act_stage == 7:
-            return True
-        return False
-
-    # 6248: remove for NM0.7; http://dev.laptop.org/ticket/6248#comment:2
-    def _getproperties_for_ip_only_reply_cb(self, *props):
-        current_ip = props[6]
-        if current_ip != self._ip_address:
-            self._ip_address = current_ip
-            if self._valid:
-                self.emit('ip-changed')
-
-    # 6248: remove for NM0.7; http://dev.laptop.org/ticket/6248#comment:2
-    def _getproperties_for_ip_only_error_cb(self, err):
-        logging.warning("Device(%s): failed to update. (%s)" % (self._op, err))
-
-    def _update_reply_cb(self, *props):
-        self._iface = props[1]
-        self._type = props[2]
-        self._udi = props[3]
-        self._active = props[4]
-        self._act_stage = props[5]
-        self._link = props[15]
-        self._caps = props[17]
-
-        if self._type == DEVICE_TYPE_802_11_WIRELESS:
-            old_strength = self._strength
-            self._strength = props[14]
-            if self._strength != old_strength:
-                if self._valid:
-                    self.emit('strength-changed')
-            self._update_networks(props[20], props[19])
-        elif self._type ==  DEVICE_TYPE_802_11_MESH_OLPC:
-            old_strength = self._strength
-            self._strength = props[14]
-            if self._strength != old_strength:
-                if self._valid:
-                    self.emit('strength-changed')
-
-        self._valid = True
-
-        # 6248: remove for NM0.7; http://dev.laptop.org/ticket/6248#comment:2
-        if props[6] != self._ip_address:
-            self._ip_address = props[6]
-            self.emit('ip-changed')
-
-        if self._is_activating():
-            self.set_state(DEVICE_STATE_ACTIVATING)
-        elif self._is_activated():
-            self.set_state(DEVICE_STATE_ACTIVATED)
-        else:
-            self.set_state(DEVICE_STATE_INACTIVE)
-
-        self.emit('initialized')
-
-    def _update_networks(self, net_ops, active_op):
-        for op in net_ops:
-            net = Network(self._client, op)
-            self._networks[op] = net
-            net.connect('initialized', lambda *args:
-                        self._net_initialized_cb(active_op, *args))
-
-    def _update_error_cb(self, err):
-        logging.debug("Device(%s): failed to update. (%s)" % (self._op, err))
-        self._valid = False
-        self.emit('init-failed')
-
-    def _net_initialized_cb(self, active_op, net, valid):
-        net_op = net.get_op()
-        if not self._networks.has_key(net_op):
-            return
-
-        if not valid:
-            # init failure
-            del self._networks[net_op]
-            return
-
-        # init success
-        if self._valid:
-            self.emit('network-appeared', net)
-        if active_op and net_op == active_op:
-            self.set_active_network(net)
-
-    def get_op(self):
-        return self._op
-
-    def get_networks(self):
-        ret = []
-        for net in self._networks.values():
-            if net.is_valid():
-                ret.append(net)
-        return ret
-
-    def get_network(self, op):
-        if self._networks.has_key(op) and self._networks[op].is_valid():
-            return self._networks[op]
-        return None
-
-    def get_network_ops(self):
-        ret = []
-        for net in self._networks.values():
-            if net.is_valid():
-                ret.append(net.get_op())
-        return ret
-
-    def get_mesh_step(self):
-        if self._type !=  DEVICE_TYPE_802_11_MESH_OLPC:
-            raise RuntimeError("Only valid for mesh devices")
-        try:
-            step = self.dev.getMeshStep(timeout=3)
-        except dbus.DBusException:
-            step = 0
-        return step
-
-    def get_frequency(self):
-        try:
-            freq = self.dev.getFrequency(timeout=3)
-        except dbus.DBusException:
-            freq = 0.0
-        # Hz -> GHz
-        self._freq = freq / 1000000000.0
-        return self._freq
-
-    def get_ip_address(self):
-        return self._ip_address
-
-    def get_strength(self):
-        return self._strength
-
-    def set_strength(self, strength):
-        if strength == self._strength:
-            return False
-
-        if strength >= 0 and strength <= 100:
-            self._strength = strength
-        else:
-            self._strength = 0
-
-        if self._valid:
-            self.emit('strength-changed')
-
-    def network_appeared(self, network):
-        # NM may emit NetworkAppeared messages before the initialization-time
-        # getProperties call completes. This means that we are in danger of
-        # instantiating the "appeared" network here, and then instantiating
-        # the same network later on when getProperties completes
-        # (_update_reply_cb calls _update_networks).
-        # We avoid this race by confirming that getProperties has completed
-        # before listening to any NetworkAppeared messages. We assume that
-        # any networks that get reported as appeared in this race window
-        # will be included in the getProperties response.
-        if not self._valid:
-            return
-
-        if self._networks.has_key(network):
-            return
-        net = Network(self._client, network)
-        self._networks[network] = net
-        net.connect('initialized', lambda *args:
-                    self._net_initialized_cb(None, *args))
-
-    def network_disappeared(self, network):
-        if not self._networks.has_key(network):
-            return
-
-        if self._valid:
-            self.emit('network-disappeared', self._networks[network])
-
-        del self._networks[network]
-
-    def set_active_network(self, network):
-        if self._active_network == network:
-            return
-
-        # Make sure the old one doesn't get a stuck state
-        if self._active_network:
-            self._active_network.set_state(NETWORK_STATE_NOTCONNECTED)
-            self._active_network.disconnect(self._active_net_sigid)
-
-        self._active_network = network
-
-        if self._active_network:
-            self._active_net_sigid = self._active_network.connect(
-                    "initialized", self._active_net_initialized)
-
-        # don't emit ssid-changed for networks that are not yet valid
-        if self._valid:
-            if self._active_network and self._active_network.is_valid():
-                self.emit('ssid-changed')
-            elif not self._active_network:
-                self.emit('ssid-changed')
-
-    def _active_net_initialized(self, net, user_data=None):
-        if self._active_network and self._active_network.is_valid():
-            self.emit('ssid-changed')
-
-    def _get_active_net_cb(self, state, net_op):
-        if not self._networks.has_key(net_op):
-            self.set_active_network(None)
-            return
-
-        self.set_active_network(self._networks[net_op])
-
-        _device_to_network_state = {
-            DEVICE_STATE_ACTIVATING : NETWORK_STATE_CONNECTING,
-            DEVICE_STATE_ACTIVATED  : NETWORK_STATE_CONNECTED,
-            DEVICE_STATE_INACTIVE   : NETWORK_STATE_NOTCONNECTED
-        }
-
-        network_state = _device_to_network_state[state]
-        self._active_network.set_state(network_state)
-
-    def _get_active_net_error_cb(self, err):
-        logging.debug("Couldn't get active network: %s" % err)
-        self.set_active_network(None)
-
-    def get_state(self):
-        return self._state
-
-    def set_state(self, state):
-        if state == self._state:
-            return
-
-        if state == DEVICE_STATE_INACTIVE:
-            self._act_stage = 0
-
-        self._state = state
-        if self._valid:
-            self.emit('state-changed')
-
-        if self._type == DEVICE_TYPE_802_11_WIRELESS:
-            if state == DEVICE_STATE_INACTIVE:
-                self.set_active_network(None)
-            else:
-                self.dev.getActiveNetwork(
-                    reply_handler=lambda *args:
-                    self._get_active_net_cb(state, *args),
-                    error_handler=self._get_active_net_error_cb)
-
-        if state == DEVICE_STATE_ACTIVATED:
-            # 6248: reimplement for NM0.7
-            #       see http://dev.laptop.org/ticket/6248#comment:2
-            self.dev.getProperties(
-                reply_handler=self._getproperties_for_ip_only_reply_cb,
-                error_handler=self._getproperties_for_ip_only_error_cb)
-
-    def set_activation_stage(self, stage):
-        if stage == self._act_stage:
-            return
-        self._act_stage = stage
-        if self._valid:
-            self.emit('activation-stage-changed')
-
-            # 6248: reimplement for NM0.7
-            #       see http://dev.laptop.org/ticket/6248#comment:2
-            self.dev.getProperties(
-                reply_handler=self._getproperties_for_ip_only_reply_cb,
-                error_handler=self._getproperties_for_ip_only_error_cb)
-
-    def get_activation_stage(self):
-        return self._act_stage
-
-    def get_ssid(self):
-        if self._active_network and self._active_network.is_valid():
-            return self._active_network.get_ssid()
-        elif not self._active_network:
-            return None
-
-    def get_active_network(self):
-        return self._active_network
-
-    def get_type(self):
-        return self._type
-
-    def is_valid(self):
-        return self._valid
-
-    def set_carrier(self, on):
-        self._link = on
-
-    def get_capabilities(self):
-        return self._caps
-
-class NMClient(gobject.GObject):
-    __gsignals__ = {
-        'device-added'     : (gobject.SIGNAL_RUN_FIRST,
-                              gobject.TYPE_NONE,
-                             ([gobject.TYPE_PYOBJECT])),
-        'device-activated' : (gobject.SIGNAL_RUN_FIRST,
-                              gobject.TYPE_NONE,
-                             ([gobject.TYPE_PYOBJECT])),
-        'device-activating': (gobject.SIGNAL_RUN_FIRST,
-                              gobject.TYPE_NONE,
-                             ([gobject.TYPE_PYOBJECT])),
-        'device-removed'   : (gobject.SIGNAL_RUN_FIRST,
-                              gobject.TYPE_NONE,
-                             ([gobject.TYPE_PYOBJECT]))
-    }
-
-    def __init__(self):
-        gobject.GObject.__init__(self)
-
-        self.nminfo = None
-        self._nm_present = False
-        self._nm_proxy = None
-        self._nm_obj = None
-        self._sig_handlers = None
-        self._update_timer = 0
-        self._devices = {}
-
-        self.nminfo = nminfo.NMInfo(self)
-        
-        self._setup_dbus()
-        if self._nm_present:
-            self._get_initial_devices()
-
-    def get_devices(self):
-        return self._devices.values()
-
-    def _get_initial_devices_reply_cb(self, ops):
-        for op in ops:
-            self._add_device(op)
-
-    def _dev_initialized_cb(self, dev):
-        self.emit('device-added', dev)
-
-    def _dev_init_failed_cb(self, dev):
-        # Device failed to initialize, likely due to dbus errors or something
-        op = dev.get_op()
-        self._remove_device(op)
-
-    def _get_initial_devices_error_cb(self, err):
-        logging.debug("Error updating devices (%s)" % err)
-
-    def _get_initial_devices(self):
-        self._nm_obj.getDevices(
-            reply_handler=self._get_initial_devices_reply_cb,
-            error_handler=self._get_initial_devices_error_cb)
-
-    def _add_device(self, dev_op):
-        if self._devices.has_key(dev_op):
-            return
-        dev = Device(self, dev_op)
-        self._devices[dev_op] = dev
-        dev.connect('init-failed', self._dev_init_failed_cb)
-        dev.connect('initialized', self._dev_initialized_cb)
-        dev.connect('state-changed', self._dev_state_changed_cb)
-
-    def _remove_device(self, dev_op):
-        if not self._devices.has_key(dev_op):
-            return
-        dev = self._devices[dev_op]
-        if dev.is_valid():
-            self.emit('device-removed', dev)
-        del self._devices[dev_op]
-
-    def _dev_state_changed_cb(self, dev):
-        op = dev.get_op()
-        if not self._devices.has_key(op) or not dev.is_valid():
-            return
-        if dev.get_state() == DEVICE_STATE_ACTIVATING:
-            self.emit('device-activating', dev)
-        elif dev.get_state() == DEVICE_STATE_ACTIVATED:
-            self.emit('device-activated', dev)
-
-    def get_device(self, dev_op):
-        if not self._devices.has_key(dev_op):
-            return None
-        return self._devices[dev_op]
-
-    def _setup_dbus(self):
-        self._sig_handlers = {
-            'StateChange': self.state_changed_sig_handler,
-            'DeviceAdded': self.device_added_sig_handler,
-            'DeviceRemoved': self.device_removed_sig_handler,
-            'DeviceActivationStage': self.device_activation_stage_sig_handler,
-            'DeviceActivating': self.device_activating_sig_handler,
-            'DeviceNowActive': self.device_now_active_sig_handler,
-            'DeviceNoLongerActive': self.device_no_longer_active_sig_handler,
-            'DeviceActivationFailed': \
-                self.device_activation_failed_sig_handler,
-            'DeviceCarrierOn': self.device_carrier_on_sig_handler,
-            'DeviceCarrierOff': self.device_carrier_off_sig_handler,
-            'DeviceStrengthChanged': \
-                self.wireless_device_strength_changed_sig_handler,
-            'WirelessNetworkAppeared': \
-                self.wireless_network_appeared_sig_handler,
-            'WirelessNetworkDisappeared': \
-                self.wireless_network_disappeared_sig_handler,
-            'WirelessNetworkStrengthChanged': \
-                self.wireless_network_strength_changed_sig_handler
-        }
-
-        try:
-            self._nm_proxy = sys_bus.get_object(NM_SERVICE, NM_PATH,
-                                                follow_name_owner_changes=True)
-            self._nm_obj = dbus.Interface(self._nm_proxy, NM_IFACE)
-        except dbus.DBusException, e:
-            logging.debug("Could not connect to NetworkManager: %s" % e)
-            self._nm_present = False
-            return
-
-        sys_bus.add_signal_receiver(self.name_owner_changed_sig_handler,
-                                         signal_name="NameOwnerChanged",
-                                         dbus_interface="org.freedesktop.DBus")
-
-        for (signal, handler) in self._sig_handlers.items():
-            sys_bus.add_signal_receiver(handler, signal_name=signal,
-                                        dbus_interface=NM_IFACE)
-
-        # Find out whether or not NMI is running
-        try:
-            bus_object = sys_bus.get_object('org.freedesktop.DBus',
-                                            '/org/freedesktop/DBus')
-            name_ = bus_object.GetNameOwner( \
-                    "org.freedesktop.NetworkManagerInfo",
-                    dbus_interface='org.freedesktop.DBus')
-            self._nm_present = True
-        except dbus.DBusException:
-            self._nm_present = False
-
-    def set_active_device(self, device, network=None,
-                          mesh_freq=None, mesh_start=None):
-        ssid = ""
-        if network:
-            ssid = network.get_ssid()
-        if device.get_type() == DEVICE_TYPE_802_11_MESH_OLPC:
-            if mesh_freq or mesh_start:
-                if mesh_freq and not mesh_start:
-                    self._nm_obj.setActiveDevice(device.get_op(),
-                                                 dbus.Double(mesh_freq))
-                elif mesh_start and not mesh_freq:
-                    self._nm_obj.setActiveDevice(device.get_op(),
-                                                 dbus.Double(0.0),
-                                                 dbus.UInt32(mesh_start))
-                else:
-                    self._nm_obj.setActiveDevice(device.get_op(),
-                                                 dbus.Double(mesh_freq),
-                                                 dbus.UInt32(mesh_start))
-            else:
-                self._nm_obj.setActiveDevice(device.get_op())
-        else:
-            self._nm_obj.setActiveDevice(device.get_op(), ssid)
-
-    def state_changed_sig_handler(self, new_state):
-        logging.debug('NM State Changed to %d' % new_state)
-
-    def device_activation_stage_sig_handler(self, device, stage):
-        logging.debug('Device Activation Stage "%s" for device %s'
-                      % (NM_DEVICE_STAGE_STRINGS[stage], device))
-        if not self._devices.has_key(device):
-            logging.debug('DeviceActivationStage, device %s does not exist'
-                          % (device))
-            return
-        self._devices[device].set_activation_stage(stage)
-
-    def device_activating_sig_handler(self, device):
-        logging.debug('DeviceActivating for %s' % (device))
-        if not self._devices.has_key(device):
-            logging.debug('DeviceActivating, device %s does not exist'
-                          % (device))
-            return
-        self._devices[device].set_state(DEVICE_STATE_ACTIVATING)
-
-    def device_now_active_sig_handler(self, device, ssid=None):
-        logging.debug('DeviceNowActive for %s' % (device))
-        if not self._devices.has_key(device):
-            logging.debug('DeviceNowActive, device %s does not exist'
-                          % (device))
-            return
-        self._devices[device].set_state(DEVICE_STATE_ACTIVATED)
-
-    def device_no_longer_active_sig_handler(self, device):
-        logging.debug('DeviceNoLongerActive for %s' % (device))
-        if not self._devices.has_key(device):
-            logging.debug('DeviceNoLongerActive, device %s does not exist'
-                          % (device))
-            return
-        self._devices[device].set_state(DEVICE_STATE_INACTIVE)
-
-    def device_activation_failed_sig_handler(self, device, ssid=None):
-        logging.debug('DeviceActivationFailed for %s' % (device))
-        if not self._devices.has_key(device):
-            logging.debug('DeviceActivationFailed, device %s does not exist'
-                          % (device))
-            return
-        self._devices[device].set_state(DEVICE_STATE_INACTIVE)
-
-    def name_owner_changed_sig_handler(self, name, old, new):
-        if name != NM_SERVICE:
-            return
-        if (old and len(old)) and (not new and not len(new)):
-            # NM went away
-            self._nm_present = False
-            devs = self._devices.keys()
-            for op in devs:
-                self._remove_device(op)
-            self._devices = {}
-        elif (not old and not len(old)) and (new and len(new)):
-            # NM started up
-            self._nm_present = True
-            self._get_initial_devices()
-
-    def device_added_sig_handler(self, device):
-        logging.debug('DeviceAdded for %s' % (device))
-        self._add_device(device)
-
-    def device_removed_sig_handler(self, device):
-        logging.debug('DeviceRemoved for %s' % (device))
-        self._remove_device(device)
-
-    def wireless_network_appeared_sig_handler(self, device, network):
-        if not self._devices.has_key(device):
-            return
-        self._devices[device].network_appeared(network)
-
-    def wireless_network_disappeared_sig_handler(self, device, network):
-        if not self._devices.has_key(device):
-            return
-        self._devices[device].network_disappeared(network)
-
-    def wireless_device_strength_changed_sig_handler(self, device, strength):
-        if not self._devices.has_key(device):
-            return
-        self._devices[device].set_strength(strength)
-
-    def wireless_network_strength_changed_sig_handler(self, device,
-                                                      network, strength):
-        if not self._devices.has_key(device):
-            return
-        net = self._devices[device].get_network(network)
-        if net:
-            net.set_strength(strength)
-
-    def device_carrier_on_sig_handler(self, device):
-        if not self._devices.has_key(device):
-            return
-        self._devices[device].set_carrier(True)
-
-    def device_carrier_off_sig_handler(self, device):
-        if not self._devices.has_key(device):
-            return
-        self._devices[device].set_carrier(False)
diff --git a/src/hardware/nminfo.py b/src/hardware/nminfo.py
deleted file mode 100644
index 9f427e0..0000000
--- a/src/hardware/nminfo.py
+++ /dev/null
@@ -1,556 +0,0 @@
-# vi: ts=4 ai noet
-#
-# Copyright (C) 2006-2007 Red Hat, Inc.
-#
-# 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 St, Fifth Floor, Boston, MA  02110-1301  USA
-
-import dbus
-import dbus.service
-import time
-import os
-import binascii
-import ConfigParser
-import logging
-
-import nmclient
-import keydialog
-import gtk
-from sugar import env
-
-IW_AUTH_KEY_MGMT_802_1X = 0x1
-IW_AUTH_KEY_MGMT_PSK = 0x2
-
-IW_AUTH_WPA_VERSION_DISABLED = 0x00000001
-IW_AUTH_WPA_VERSION_WPA      = 0x00000002
-IW_AUTH_WPA_VERSION_WPA2     = 0x00000004
-
-NM_AUTH_TYPE_WPA_PSK_AUTO = 0x00000000
-IW_AUTH_CIPHER_NONE   = 0x00000001
-IW_AUTH_CIPHER_WEP40  = 0x00000002
-IW_AUTH_CIPHER_TKIP   = 0x00000004
-IW_AUTH_CIPHER_CCMP   = 0x00000008
-IW_AUTH_CIPHER_WEP104 = 0x00000010
-
-IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001
-IW_AUTH_ALG_SHARED_KEY  = 0x00000002
-
-NM_INFO_IFACE = 'org.freedesktop.NetworkManagerInfo'
-NM_INFO_PATH = '/org/freedesktop/NetworkManagerInfo'
-
-
-class NoNetworks(dbus.DBusException):
-    def __init__(self):
-        dbus.DBusException.__init__(self)
-        self._dbus_error_name = NM_INFO_IFACE + '.NoNetworks'
-
-class CanceledKeyRequestError(dbus.DBusException):
-    def __init__(self):
-        dbus.DBusException.__init__(self)
-        self._dbus_error_name = NM_INFO_IFACE + '.CanceledError'
-
-
-class NetworkInvalidError(Exception):
-    pass
-
-
-class NMConfig(ConfigParser.ConfigParser):
-    def get_bool(self, section, name):
-        opt = self.get(section, name)
-        if type(opt) == str:
-            if opt.lower() == 'yes' or opt.lower() == 'true':
-                return True
-            elif opt.lower() == 'no' or opt.lower() == 'false':
-                return False
-        raise ValueError("Invalid format for %s/%s.  Should be one of" \
-                         " [yes, no, true, false]." % (section, name))
-
-    def get_list(self, section, name):
-        opt = self.get(section, name)
-        if type(opt) != str or not len(opt):
-            return []
-        try:
-            return opt.split()
-        except Exception:
-            raise ValueError("Invalid format for %s/%s.  Should be a" \
-                             " space-separate list." % (section, name))
-
-    def get_int(self, section, name):
-        opt = self.get(section, name)
-        try:
-            return int(opt)
-        except ValueError:
-            raise ValueError("Invalid format for %s/%s.  Should be a" \
-                             " valid integer." % (section, name))
-
-    def get_float(self, section, name):
-        opt = self.get(section, name)
-        try:
-            return float(opt)
-        except ValueError:
-            raise ValueError("Invalid format for %s/%s.  Should be a" \
-                             " valid float." % (section, name))
-
-
-NETWORK_TYPE_UNKNOWN = 0
-NETWORK_TYPE_ALLOWED = 1
-NETWORK_TYPE_INVALID = 2
-
-
-class Security(object):
-    def __init__(self, we_cipher):
-        self._we_cipher = we_cipher
-        self._key = None
-        self._auth_alg = None
-
-    def read_from_config(self, cfg, name):
-        pass
-
-    def read_from_args(self, args):
-        pass
-
-    def new_from_config(cfg, name):
-        security = None
-        we_cipher = cfg.get_int(name, "we_cipher")
-        if we_cipher == IW_AUTH_CIPHER_NONE:
-            security = Security(we_cipher)
-        elif we_cipher == IW_AUTH_CIPHER_WEP40 or \
-                        we_cipher == IW_AUTH_CIPHER_WEP104:
-            security = WEPSecurity(we_cipher)
-        elif we_cipher == NM_AUTH_TYPE_WPA_PSK_AUTO or \
-                        we_cipher == IW_AUTH_CIPHER_CCMP or \
-                        we_cipher == IW_AUTH_CIPHER_TKIP:
-            security = WPASecurity(we_cipher)
-        else:
-            raise ValueError("Unsupported security combo")
-        security.read_from_config(cfg, name)
-        return security
-    new_from_config = staticmethod(new_from_config)
-
-    def new_from_args(we_cipher, args):
-        security = None
-        try:
-            if we_cipher == IW_AUTH_CIPHER_NONE:
-                security = Security(we_cipher)
-            elif we_cipher == IW_AUTH_CIPHER_WEP40 or \
-                            we_cipher == IW_AUTH_CIPHER_WEP104:
-                security = WEPSecurity(we_cipher)
-            elif we_cipher == NM_AUTH_TYPE_WPA_PSK_AUTO or \
-                            we_cipher == IW_AUTH_CIPHER_CCMP or \
-                            we_cipher == IW_AUTH_CIPHER_TKIP:
-                security = WPASecurity(we_cipher)
-            else:
-                raise ValueError("Unsupported security combo")
-            security.read_from_args(args)
-        except ValueError, e:
-            logging.debug("Error reading security information: %s" % e)
-            del security
-            return None
-        return security
-    new_from_args = staticmethod(new_from_args)
-
-    def get_properties(self):
-        return [dbus.Int32(self._we_cipher)]
-
-    def write_to_config(self, section, config):
-        config.set(section, "we_cipher", self._we_cipher)
-
-
-class WEPSecurity(Security):
-    def read_from_args(self, args):
-        if len(args) != 2:
-            raise ValueError("not enough arguments")
-        key = args[0]
-        auth_alg = args[1]
-        if isinstance(key, unicode):
-            key = key.encode()
-        if not isinstance(key, str):
-            raise ValueError("wrong argument type for key")
-        if not isinstance(auth_alg, int):
-            raise ValueError("wrong argument type for auth_alg")
-        self._key = key
-        self._auth_alg = auth_alg
-
-    def read_from_config(self, cfg, name):
-        # Key should be a hex encoded string
-        self._key = cfg.get(name, "key")
-        if self._we_cipher == IW_AUTH_CIPHER_WEP40 and len(self._key) != 10:
-            raise ValueError("Key length not right for 40-bit WEP")
-        if self._we_cipher == IW_AUTH_CIPHER_WEP104 and len(self._key) != 26:
-            raise ValueError("Key length not right for 104-bit WEP")
-
-        try:
-            binascii.a2b_hex(self._key)
-        except TypeError:
-            raise ValueError("Key was not a hexadecimal string.")
-            
-        self._auth_alg = cfg.get_int(name, "auth_alg")
-        if self._auth_alg != IW_AUTH_ALG_OPEN_SYSTEM and \
-                self._auth_alg != IW_AUTH_ALG_SHARED_KEY:
-            raise ValueError("Invalid authentication algorithm %d"
-                             % self._auth_alg)
-
-    def get_properties(self):
-        args = Security.get_properties(self)
-        args.append(dbus.String(self._key))
-        args.append(dbus.Int32(self._auth_alg))
-        return args
-
-    def write_to_config(self, section, config):
-        Security.write_to_config(self, section, config)
-        config.set(section, "key", self._key)
-        config.set(section, "auth_alg", self._auth_alg)
-
-class WPASecurity(Security):
-    def __init__(self, we_cipher):
-        Security.__init__(self, we_cipher)
-        self._wpa_ver = None
-        self._key_mgmt = None
-
-    def read_from_args(self, args):
-        if len(args) != 3:
-            raise ValueError("not enough arguments")
-        key = args[0]
-        if isinstance(key, unicode):
-            key = key.encode()
-        if not isinstance(key, str):
-            raise ValueError("wrong argument type for key")
-
-        wpa_ver = args[1]
-        if not isinstance(wpa_ver, int):
-            raise ValueError("wrong argument type for WPA version")
-
-        key_mgmt = args[2]
-        if not isinstance(key_mgmt, int):
-            raise ValueError("wrong argument type for WPA key management")
-        if not key_mgmt & IW_AUTH_KEY_MGMT_PSK:
-            raise ValueError("Key management types other than" \
-                             " PSK are not supported")
-
-        self._key = key
-        self._wpa_ver = wpa_ver
-        self._key_mgmt = key_mgmt
-
-    def read_from_config(self, cfg, name):
-        # Key should be a hex encoded string
-        self._key = cfg.get(name, "key")
-        if len(self._key) != 64:
-            raise ValueError("Key length not right for WPA-PSK")
-
-        try:
-            binascii.a2b_hex(self._key)
-        except TypeError:
-            raise ValueError("Key was not a hexadecimal string.")
-            
-        self._wpa_ver = cfg.get_int(name, "wpa_ver")
-        if self._wpa_ver != IW_AUTH_WPA_VERSION_WPA and \
-                self._wpa_ver != IW_AUTH_WPA_VERSION_WPA2:
-            raise ValueError("Invalid WPA version %d" % self._wpa_ver)
-
-        self._key_mgmt = cfg.get_int(name, "key_mgmt")
-        if not self._key_mgmt & IW_AUTH_KEY_MGMT_PSK:
-            raise ValueError("Invalid WPA key management option %d"
-                             % self._key_mgmt)
-
-    def get_properties(self):
-        args = Security.get_properties(self)
-        args.append(dbus.String(self._key))
-        args.append(dbus.Int32(self._wpa_ver))
-        args.append(dbus.Int32(self._key_mgmt))
-        return args
-
-    def write_to_config(self, section, config):
-        Security.write_to_config(self, section, config)
-        config.set(section, "key", self._key)
-        config.set(section, "wpa_ver", self._wpa_ver)
-        config.set(section, "key_mgmt", self._key_mgmt)
-
-
-class Network:
-    def __init__(self, ssid):
-        self.ssid = ssid
-        self.timestamp = int(time.time())
-        self.bssids = []
-        self.we_cipher = 0
-        self._security = None
-
-    def get_properties(self):
-        bssid_list = dbus.Array([], signature="s")
-        for item in self.bssids:
-            bssid_list.append(dbus.String(item))
-        args = [dbus.String(self.ssid), dbus.Int32(self.timestamp),
-                dbus.Boolean(True), bssid_list]
-        args += self._security.get_properties()
-        return tuple(args)
-
-    def get_security(self):
-        return self._security.get_properties()
-
-    def set_security(self, security):
-        self._security = security
-
-    def read_from_args(self, auto, bssid, we_cipher, args):
-        if auto == False:
-            self.timestamp = int(time.time())
-        if not bssid in self.bssids:
-            self.bssids.append(bssid)
-
-        self._security = Security.new_from_args(we_cipher, args)
-        if not self._security:
-            raise NetworkInvalidError("Invalid security information")
-
-    def read_from_config(self, config):
-        try:
-            self.timestamp = config.get_int(self.ssid, "timestamp")
-        except (ConfigParser.NoOptionError, ValueError), e:
-            raise NetworkInvalidError(e)
-
-        try:
-            self._security = Security.new_from_config(config, self.ssid)
-        except Exception, e:
-            raise NetworkInvalidError(e)
-
-        # The following don't need to be present
-        try:
-            self.bssids = config.get_list(self.ssid, "bssids")
-        except (ConfigParser.NoOptionError, ValueError), e:
-            logging.debug("Error reading bssids: %s" % e)
-
-    def write_to_config(self, config):
-        try:
-            config.add_section(self.ssid)
-            config.set(self.ssid, "timestamp", self.timestamp)
-            if len(self.bssids) > 0:
-                opt = " "
-                opt = opt.join(self.bssids)
-                config.set(self.ssid, "bssids", opt)
-            self._security.write_to_config(self.ssid, config)
-        except Exception, e:
-            logging.debug("Error writing '%s': %s" % (self.ssid, e))
-
-
-class NotFoundError(dbus.DBusException):
-    pass
-class UnsupportedError(dbus.DBusException):
-    pass
-
-class NMInfoDBusServiceHelper(dbus.service.Object):
-    def __init__(self, parent):
-        self._parent = parent
-        bus = dbus.SystemBus()
-
-        # If NMI is already around, don't grab the NMI service
-        bus_object = bus.get_object('org.freedesktop.DBus',
-                                    '/org/freedesktop/DBus')
-        name = None
-        try:
-            name = bus_object.GetNameOwner( \
-                    "org.freedesktop.NetworkManagerInfo",
-                    dbus_interface='org.freedesktop.DBus')
-        except dbus.DBusException:
-            logging.debug("Error getting owner of NMI")
-        if name:
-            logging.info("NMI service already owned by %s, won't claim it."
-                          % name)
-
-        bus_name = dbus.service.BusName(NM_INFO_IFACE, bus=bus)
-        dbus.service.Object.__init__(self, bus_name, NM_INFO_PATH)
-
-    @dbus.service.method(NM_INFO_IFACE, in_signature='i', out_signature='as')
-    def getNetworks(self, net_type):
-        ssids = self._parent.get_networks(net_type)
-        if len(ssids) > 0:
-            return dbus.Array(ssids)
-
-        raise NoNetworks()
-
-    @dbus.service.method(NM_INFO_IFACE, in_signature='si',
-                         async_callbacks=('async_cb', 'async_err_cb'))
-    def getNetworkProperties(self, ssid, net_type, async_cb, async_err_cb):
-        self._parent.get_network_properties(ssid, net_type,
-                                            async_cb, async_err_cb)
-
-    @dbus.service.method(NM_INFO_IFACE)
-    def updateNetworkInfo(self, ssid, bauto, bssid, cipher, *args):
-        self._parent.update_network_info(ssid, bauto, bssid, cipher, args)
-
-    @dbus.service.method(NM_INFO_IFACE,
-                         async_callbacks=('async_cb', 'async_err_cb'))
-    def getKeyForNetwork(self, dev_path, net_path, ssid, attempt,
-                         new_key, async_cb, async_err_cb):
-        self._parent.get_key_for_network(dev_path, net_path, ssid,
-                attempt, new_key, async_cb, async_err_cb)
-
-    @dbus.service.method(NM_INFO_IFACE)
-    def cancelGetKeyForNetwork(self):
-        self._parent.cancel_get_key_for_network()
-
-class NMInfo(object):
-    def __init__(self, client):
-        profile_path = env.get_profile_path()
-        self._cfg_file = os.path.join(profile_path, "nm", "networks.cfg")
-        self._nmclient = client
-        self._allowed_networks = self._read_config()
-        self._dbus_helper = NMInfoDBusServiceHelper(self)
-        self._key_dialog = None
-
-    def save_config(self):
-        self._write_config(self._allowed_networks)
-
-    def _read_config(self):
-        if not os.path.exists(os.path.dirname(self._cfg_file)):
-            os.makedirs(os.path.dirname(self._cfg_file), 0755)
-        if not os.path.exists(self._cfg_file):
-            self._write_config({})
-            return {}
-
-        config = NMConfig()
-        config.read(self._cfg_file)
-        networks = {}
-        for name in config.sections():
-            try:
-                net = Network(name)
-                net.read_from_config(config)
-                networks[name] = net
-            except Exception, e:
-                logging.error("Error when processing config for" \
-                              " the network %s: %r" % (name, e))
-
-        del config
-        return networks
-
-    def _write_config(self, networks):
-        fp = open(self._cfg_file, 'w')
-        config = NMConfig()
-        for net in networks.values():
-            net.write_to_config(config)
-        config.write(fp)
-        fp.close()
-        del config
-
-    def get_networks(self, net_type):
-        if net_type != NETWORK_TYPE_ALLOWED:
-            raise ValueError("Bad network type")
-        nets = []
-        for net in self._allowed_networks.values():
-            nets.append(net.ssid)
-        logging.debug("Returning networks: %s" % nets)
-        return nets
-
-    def get_network_properties(self, ssid, net_type, async_cb, async_err_cb):
-        if not isinstance(ssid, unicode):
-            async_err_cb(ValueError("Invalid arguments; ssid must be unicode."))
-        if net_type != NETWORK_TYPE_ALLOWED:
-            async_err_cb(ValueError("Bad network type"))
-        if not self._allowed_networks.has_key(ssid):
-            async_err_cb(NotFoundError("Network '%s' not found." % ssid))
-        network = self._allowed_networks[ssid]
-        props = network.get_properties()
-
-        # DBus workaround: the normal method return handler wraps
-        # the returned arguments in a tuple and then converts that to a
-        # struct, but NetworkManager expects a plain list of arguments.
-        # It turns out that the async callback method return code _doesn't_
-        # wrap the returned arguments in a tuple, so as a workaround use
-        # the async callback stuff here even though we're not doing it
-        # asynchronously.
-        async_cb(*props)
-
-    def update_network_info(self, ssid, auto, bssid, we_cipher, args):
-        if not isinstance(ssid, unicode):
-            raise ValueError("Invalid arguments; ssid must be unicode.")
-        if self._allowed_networks.has_key(ssid):
-            del self._allowed_networks[ssid]
-        net = Network(ssid)
-        try:
-            net.read_from_args(auto, bssid, we_cipher, args)
-            logging.debug("Updated network information for '%s'." % ssid)
-            self._allowed_networks[ssid] = net
-            self.save_config()
-        except NetworkInvalidError, e:
-            logging.debug("Error updating network information: %s" % e)
-            del net
-
-    def get_key_for_network(self, dev_op, net_op, ssid, attempt,
-                            new_key, async_cb, async_err_cb):
-        if not isinstance(ssid, unicode):
-            raise ValueError("Invalid arguments; ssid must be unicode.")
-        if self._allowed_networks.has_key(ssid) and not new_key:
-            # We've got the info already
-            net = self._allowed_networks[ssid]
-            async_cb(tuple(net.get_security()))
-            return
-
-        # Otherwise, ask the user for it
-        net = None
-        dev = self._nmclient.get_device(dev_op)
-        if not dev:
-            async_err_cb(NotFoundError("Device was unknown."))
-            return
-
-        if dev.get_type() == nmclient.DEVICE_TYPE_802_3_ETHERNET:
-            # We don't support wired 802.1x yet...
-            async_err_cb(UnsupportedError("Device type is unsupported by NMI."))
-            return
-
-        net = dev.get_network(net_op)
-        if not net:
-            async_err_cb(NotFoundError("Network was unknown."))
-            return
-
-        self._key_dialog = keydialog.new_key_dialog(net, async_cb, async_err_cb)
-        self._key_dialog.connect("response", self._key_dialog_response_cb)
-        self._key_dialog.connect("destroy", self._key_dialog_destroy_cb)
-        self._key_dialog.show_all()
-
-    def _key_dialog_destroy_cb(self, widget, data=None):
-        if widget != self._key_dialog:
-            return
-        self._key_dialog_response_cb(widget, gtk.RESPONSE_CANCEL)
-
-    def _key_dialog_response_cb(self, widget, response_id):
-        if widget != self._key_dialog:
-            return
-
-        (async_cb, async_err_cb) = self._key_dialog.get_callbacks()
-        security = None
-        if response_id == gtk.RESPONSE_OK:
-            security = self._key_dialog.create_security()
-        self._key_dialog = None
-        widget.destroy()
-
-        if response_id in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_NONE]:
-            # key dialog dialog was canceled; send the error back to NM
-            async_err_cb(CanceledKeyRequestError())
-        elif response_id == gtk.RESPONSE_OK:
-            if not security:
-                raise RuntimeError("Invalid security arguments.")
-            props = security.get_properties()
-            a = tuple(props)
-            async_cb(*a)
-        else:
-            raise RuntimeError("Unhandled key dialog response %d" % response_id)
-
-    def cancel_get_key_for_network(self):
-        # Close the wireless key dialog and just have it return
-        # with the 'canceled' argument set to true
-        if not self._key_dialog:
-            return
-        self._key_dialog_destroy_cb(self._key_dialog)
-
-    # this method is invoked directly in-process (not by DBus).
-    def delete_all_networks(self):
-        self._allowed_networks = {}
-        self.save_config()
-
diff --git a/src/model/Makefile.am b/src/model/Makefile.am
index 0b7d14c..c89ce47 100644
--- a/src/model/Makefile.am
+++ b/src/model/Makefile.am
@@ -3,12 +3,12 @@ SUBDIRS = devices
 sugardir = $(pkgdatadir)/shell/model
 sugar_PYTHON =			\
 	__init__.py		\
-	accesspointmodel.py	\
 	BuddyModel.py		\
 	Friends.py		\
 	Invites.py		\
 	Owner.py		\
-	MeshModel.py		\
 	shellmodel.py		\
 	homeactivity.py		\
-	homemodel.py
+	homemodel.py		\
+	network.py		\
+	neighborhood.py
diff --git a/src/model/MeshModel.py b/src/model/MeshModel.py
deleted file mode 100644
index fa33035..0000000
--- a/src/model/MeshModel.py
+++ /dev/null
@@ -1,237 +0,0 @@
-# Copyright (C) 2006-2007 Red Hat, Inc.
-#
-# 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 St, Fifth Floor, Boston, MA  02110-1301  USA
-
-import gobject
-
-from sugar.graphics.xocolor import XoColor
-from sugar.presence import presenceservice
-from sugar import activity
-
-from model.BuddyModel import BuddyModel
-from model.accesspointmodel import AccessPointModel
-from hardware import hardwaremanager
-from hardware import nmclient
-
-class ActivityModel:
-    def __init__(self, act, bundle):
-        self.activity = act
-        self.bundle = bundle
-
-    def get_id(self):
-        return self.activity.props.id
-        
-    def get_icon_name(self):
-        return self.bundle.icon
-    
-    def get_color(self):
-        return XoColor(self.activity.props.color)
-
-    def get_bundle_id(self):
-        return self.bundle.bundle_id
-
-class MeshModel(gobject.GObject):
-    __gsignals__ = {
-        'activity-added':       (gobject.SIGNAL_RUN_FIRST,
-                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
-        'activity-removed':     (gobject.SIGNAL_RUN_FIRST,
-                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
-        'buddy-added':          (gobject.SIGNAL_RUN_FIRST,
-                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
-        'buddy-moved':          (gobject.SIGNAL_RUN_FIRST,
-                                 gobject.TYPE_NONE,
-                                ([gobject.TYPE_PYOBJECT,
-                                  gobject.TYPE_PYOBJECT])),
-        'buddy-removed':        (gobject.SIGNAL_RUN_FIRST,
-                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
-        'access-point-added':   (gobject.SIGNAL_RUN_FIRST,
-                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
-        'access-point-removed': (gobject.SIGNAL_RUN_FIRST,
-                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
-        'mesh-added':           (gobject.SIGNAL_RUN_FIRST,
-                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
-        'mesh-removed':         (gobject.SIGNAL_RUN_FIRST,
-                                 gobject.TYPE_NONE, ([]))
-    }
-
-    def __init__(self):
-        gobject.GObject.__init__(self)
-
-        self._activities = {}
-        self._buddies = {}
-        self._access_points = {}
-        self._mesh = None
-
-        self._pservice = presenceservice.get_instance()
-        self._pservice.connect("activity-appeared",
-                               self._activity_appeared_cb)
-        self._pservice.connect('activity-disappeared',
-                               self._activity_disappeared_cb)
-        self._pservice.connect("buddy-appeared",
-                               self._buddy_appeared_cb)
-        self._pservice.connect("buddy-disappeared",
-                               self._buddy_disappeared_cb)
-
-        # Add any buddies the PS knows about already
-        self._pservice.get_buddies_async(reply_handler=self._get_buddies_cb)
-
-        self._pservice.get_activities_async(
-                reply_handler=self._get_activities_cb)
-
-        network_manager = hardwaremanager.get_network_manager()
-        if network_manager:
-            for nm_device in network_manager.get_devices():
-                self._add_network_device(nm_device)
-            network_manager.connect('device-added',
-                                    self._nm_device_added_cb)
-            network_manager.connect('device-removed',
-                                    self._nm_device_removed_cb)
-
-    def _get_buddies_cb(self, buddy_list):
-        for buddy in buddy_list:
-            self._buddy_appeared_cb(self._pservice, buddy)
-
-    def _get_activities_cb(self, activity_list):
-        for act in activity_list:
-            self._check_activity(act)
-
-    def _nm_device_added_cb(self, manager, nm_device):
-        self._add_network_device(nm_device)
-
-    def _nm_device_removed_cb(self, manager, nm_device):
-        self._remove_network_device(nm_device)
-
-    def _nm_network_appeared_cb(self, nm_device, nm_network):
-        self._add_access_point(nm_device, nm_network)
-
-    def _nm_network_disappeared_cb(self, nm_device, nm_network):
-        if self._access_points.has_key(nm_network.get_op()):
-            ap = self._access_points[nm_network.get_op()]
-            self._remove_access_point(ap)
-
-    def _add_network_device(self, nm_device):
-        dtype = nm_device.get_type()
-        if dtype == nmclient.DEVICE_TYPE_802_11_WIRELESS:
-            for nm_network in nm_device.get_networks():
-                self._add_access_point(nm_device, nm_network)
-
-            nm_device.connect('network-appeared',
-                              self._nm_network_appeared_cb)
-            nm_device.connect('network-disappeared',
-                              self._nm_network_disappeared_cb)
-        elif dtype == nmclient.DEVICE_TYPE_802_11_MESH_OLPC:
-            self._mesh = nm_device
-            self.emit('mesh-added', self._mesh)
-
-    def _remove_network_device(self, nm_device):
-        if nm_device == self._mesh:
-            self._mesh = None
-            self.emit('mesh-removed')
-        elif nm_device.get_type() == nmclient.DEVICE_TYPE_802_11_WIRELESS:
-            aplist = self._access_points.values()
-            for ap in aplist:
-                if ap.get_nm_device() == nm_device:
-                    self._remove_access_point(ap)
-
-    def _add_access_point(self, nm_device, nm_network):
-        model = AccessPointModel(nm_device, nm_network)
-        self._access_points[model.get_id()] = model
-        self.emit('access-point-added', model)
-
-    def _remove_access_point(self, ap):
-        if not self._access_points.has_key(ap.get_id()):
-            return
-        self.emit('access-point-removed', ap)
-        del self._access_points[ap.get_id()]
-
-    def get_mesh(self):
-        return self._mesh
-
-    def get_access_points(self):
-        return self._access_points.values()
-
-    def get_activities(self):
-        return self._activities.values()
-
-    def get_buddies(self):
-        return self._buddies.values()
-
-    def _buddy_activity_changed_cb(self, model, cur_activity):
-        if not self._buddies.has_key(model.get_key()):
-            return
-        if cur_activity and self._activities.has_key(cur_activity.props.id):
-            activity_model = self._activities[cur_activity.props.id]
-            self.emit('buddy-moved', model, activity_model)
-        else:
-            self.emit('buddy-moved', model, None)
-
-    def _buddy_appeared_cb(self, pservice, buddy):
-        if self._buddies.has_key(buddy.props.key):
-            return
-
-        model = BuddyModel(buddy=buddy)
-        model.connect('current-activity-changed',
-                      self._buddy_activity_changed_cb)
-        self._buddies[buddy.props.key] = model
-        self.emit('buddy-added', model)
-
-        cur_activity = buddy.props.current_activity
-        if cur_activity:
-            self._buddy_activity_changed_cb(model, cur_activity)
-
-    def _buddy_disappeared_cb(self, pservice, buddy):
-        if not self._buddies.has_key(buddy.props.key):
-            return
-        self.emit('buddy-removed', self._buddies[buddy.props.key])
-        del self._buddies[buddy.props.key]
-
-    def _activity_appeared_cb(self, pservice, act):
-        self._check_activity(act)
-
-    def _check_activity(self, presence_activity):
-        registry = activity.get_registry()
-        bundle = registry.get_activity(presence_activity.props.type)
-        if not bundle:
-            return
-        if self.has_activity(presence_activity.props.id):
-            return
-        self.add_activity(bundle, presence_activity)
-
-    def has_activity(self, activity_id):
-        return self._activities.has_key(activity_id)
-
-    def get_activity(self, activity_id):
-        if self.has_activity(activity_id):
-            return self._activities[activity_id]
-        else:
-            return None
-
-    def add_activity(self, bundle, act):
-        model = ActivityModel(act, bundle)
-        self._activities[model.get_id()] = model
-        self.emit('activity-added', model)
-
-        for buddy in self._pservice.get_buddies():
-            cur_activity = buddy.props.current_activity
-            key = buddy.props.key
-            if cur_activity == activity and self._buddies.has_key(key):
-                buddy_model = self._buddies[key]
-                self.emit('buddy-moved', buddy_model, model)
-
-    def _activity_disappeared_cb(self, pservice, act):
-        if self._activities.has_key(act.props.id):
-            activity_model = self._activities[act.props.id]
-            self.emit('activity-removed', activity_model)
-            del self._activities[act.props.id]
diff --git a/src/model/accesspointmodel.py b/src/model/accesspointmodel.py
deleted file mode 100644
index f464f75..0000000
--- a/src/model/accesspointmodel.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright (C) 2006-2007 Red Hat, Inc.
-#
-# 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 St, Fifth Floor, Boston, MA  02110-1301  USA
-
-import gobject
-
-from hardware import nmclient
-
-STATE_CONNECTING   = 0
-STATE_CONNECTED    = 1
-STATE_NOTCONNECTED = 2
-
-_nm_state_to_state = {
-    nmclient.NETWORK_STATE_CONNECTED    : STATE_CONNECTED,
-    nmclient.NETWORK_STATE_CONNECTING   : STATE_CONNECTING,
-    nmclient.NETWORK_STATE_NOTCONNECTED : STATE_NOTCONNECTED
-}
-
-class AccessPointModel(gobject.GObject):
-    __gproperties__ = {
-        'name'     : (str, None, None, None,
-                      gobject.PARAM_READABLE),
-        'strength' : (int, None, None, 0, 100, 0,
-                      gobject.PARAM_READABLE),
-        'state'    : (int, None, None, STATE_CONNECTING,
-                      STATE_NOTCONNECTED, 0, gobject.PARAM_READABLE),
-        'capabilities' : (int, None, None, 0, 0x7FFFFFFF, 0,
-                      gobject.PARAM_READABLE),
-        'mode'     : (int, None, None, 0, 6, 0, gobject.PARAM_READABLE)
-    }
-
-    def __init__(self, nm_device, nm_network):
-        gobject.GObject.__init__(self)
-        self._nm_network = nm_network
-        self._nm_device = nm_device
-
-        self._nm_network.connect('strength-changed',
-                                 self._strength_changed_cb)
-        self._nm_network.connect('state-changed',
-                                 self._state_changed_cb)
-
-    def _strength_changed_cb(self, nm_network):
-        self.notify('strength')
-
-    def _state_changed_cb(self, nm_network):
-        self.notify('state')
-
-    def get_id(self):
-        return self._nm_network.get_op()
-
-    def get_nm_device(self):
-        return self._nm_device
-
-    def get_nm_network(self):
-        return self._nm_network
-
-    def do_get_property(self, pspec):
-        if pspec.name == 'strength':
-            return self._nm_network.get_strength()
-        elif pspec.name == 'name':
-            return self._nm_network.get_ssid()
-        elif pspec.name == 'state':
-            nm_state = self._nm_network.get_state()
-            return _nm_state_to_state[nm_state]
-        elif pspec.name == 'capabilities':
-            return self._nm_network.get_caps()
-        elif pspec.name == 'mode':
-            return self._nm_network.get_mode()
diff --git a/src/model/devices/device.py b/src/model/devices/device.py
index 3273da9..6a62088 100644
--- a/src/model/devices/device.py
+++ b/src/model/devices/device.py
@@ -16,20 +16,9 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 import gobject
-from hardware import nmclient
 
 from sugar import util
 
-STATE_ACTIVATING = 0
-STATE_ACTIVATED  = 1
-STATE_INACTIVE   = 2
-
-nm_state_to_state = {
-    nmclient.DEVICE_STATE_ACTIVATING : STATE_ACTIVATING,
-    nmclient.DEVICE_STATE_ACTIVATED  : STATE_ACTIVATED,
-    nmclient.DEVICE_STATE_INACTIVE   : STATE_INACTIVE
-}
-
 class Device(gobject.GObject):
     def __init__(self, device_id=None):
         gobject.GObject.__init__(self)
diff --git a/src/model/devices/devicesmodel.py b/src/model/devices/devicesmodel.py
index f328109..aa9446c 100644
--- a/src/model/devices/devicesmodel.py
+++ b/src/model/devices/devicesmodel.py
@@ -19,13 +19,15 @@ import logging
 import gobject
 import dbus
 
-from model.devices import device
 from model.devices.network import wireless
-from model.devices.network import mesh
 from model.devices import battery
 from model.devices import speaker
-from hardware import hardwaremanager
-from hardware import nmclient
+from model import network
+
+_NM_SERVICE = 'org.freedesktop.NetworkManager'
+_NM_IFACE = 'org.freedesktop.NetworkManager'
+_NM_PATH = '/org/freedesktop/NetworkManager'
+_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device'
 
 class DevicesModel(gobject.GObject):
     __gsignals__ = {
@@ -39,6 +41,8 @@ class DevicesModel(gobject.GObject):
    
     def __init__(self):
         gobject.GObject.__init__(self)
+        self._bus = dbus.SystemBus()
+        self._netmgr = None
 
         self._devices = {}
         self._sigids = {}
@@ -62,73 +66,46 @@ class DevicesModel(gobject.GObject):
             self.add_device(battery.Device(udi))
 
     def _observe_network_manager(self):
-        network_manager = hardwaremanager.get_network_manager()
-        if not network_manager:
+        try:
+            obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
+            self._netmgr = dbus.Interface(obj, _NM_IFACE)
+        except dbus.DBusException:
+            logging.debug('%s service not available', _NM_SERVICE)
             return
 
-        for dev in network_manager.get_devices():
-            self._check_network_device(dev)
-
-        network_manager.connect('device-added',
-                                self._network_device_added_cb)
-        network_manager.connect('device-activating',
-                                self._network_device_activating_cb)
-        network_manager.connect('device-activated',
-                                self._network_device_activated_cb)
-        network_manager.connect('device-removed',
-                                self._network_device_removed_cb)
-
-    def _network_device_added_cb(self, network_manager, nm_device):
-        state = nm_device.get_state()
-        if state == nmclient.DEVICE_STATE_ACTIVATING \
-                or state == nmclient.DEVICE_STATE_ACTIVATED:
-            self._check_network_device(nm_device)
-
-    def _network_device_activating_cb(self, network_manager, nm_device):
-        self._check_network_device(nm_device)
-
-    def _network_device_activated_cb(self, network_manager, nm_device):
-        pass
-
-    def _network_device_removed_cb(self, network_manager, nm_device):
-        if self._devices.has_key(str(nm_device.get_op())):
-            self.remove_device(self._get_network_device(nm_device))
-
-    def _check_network_device(self, nm_device):
-        if not nm_device.is_valid():
-            logging.debug("Device %s not valid" % nm_device.get_op())
-            return
+        self._netmgr.GetDevices(reply_handler=self.__get_devices_reply_cb,
+                                error_handler=self.__get_devices_error_cb)
 
-        dtype = nm_device.get_type()
-        if dtype == nmclient.DEVICE_TYPE_802_11_WIRELESS \
-           or dtype == nmclient.DEVICE_TYPE_802_11_MESH_OLPC:
-            self._add_network_device(nm_device)
+        self._bus.add_signal_receiver(self.__device_added_cb,
+                                      signal_name='DeviceAdded',
+                                      dbus_interface=_NM_IFACE)
+        self._bus.add_signal_receiver(self.__device_removed_cb,
+                                      signal_name='DeviceRemoved',
+                                      dbus_interface=_NM_IFACE)
 
-    def _get_network_device(self, nm_device):
-        return self._devices[str(nm_device.get_op())]
+    def __get_devices_reply_cb(self, devices_o):
+        for dev_o in devices_o:
+            self._check_device(dev_o)
 
-    def _network_device_state_changed_cb(self, dev, param):
-        if dev.props.state == device.STATE_INACTIVE:
-            self.remove_device(dev)
+    def __get_devices_error_cb(self, err):
+        logging.error('Failed to get devices: %s', err)
 
-    def _add_network_device(self, nm_device):
-        if self._devices.has_key(str(nm_device.get_op())):
-            logging.debug("Tried to add device %s twice" % nm_device.get_op())
-            return
+    def _check_device(self, device_o):
+        nm_device = self._bus.get_object(_NM_SERVICE, device_o)
+        props = dbus.Interface(nm_device, 'org.freedesktop.DBus.Properties')
+
+        device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
+        if device_type == network.DEVICE_TYPE_802_11_WIRELESS:
+            device = wireless.Device(nm_device)
+            self.add_device(device)
+
+    def __device_added_cb(self, device_o):
+        self._check_device(device_o)
 
-        dtype = nm_device.get_type()
-        if dtype == nmclient.DEVICE_TYPE_802_11_WIRELESS:
-            dev = wireless.Device(nm_device)
-            self.add_device(dev)
-            sigid = dev.connect('notify::state',
-                                self._network_device_state_changed_cb)
-            self._sigids[dev] = sigid
-        if dtype == nmclient.DEVICE_TYPE_802_11_MESH_OLPC:
-            dev = mesh.Device(nm_device)
-            self.add_device(dev)
-            sigid = dev.connect('notify::state',
-                                self._network_device_state_changed_cb)
-            self._sigids[dev] = sigid
+    def __device_removed_cb(self, device_o):
+        if device_o in self._devices:
+            device = self._devices[device_o]
+            self.remove_device(device)
 
     def __iter__(self):
         return iter(self._devices.values())
@@ -139,6 +116,7 @@ class DevicesModel(gobject.GObject):
 
     def remove_device(self, dev):
         self.emit('device-disappeared', self._devices[dev.get_id()])
-        dev.disconnect(self._sigids[dev])
-        del self._sigids[dev]
+        if dev in self._sigids:
+            dev.disconnect(self._sigids[dev])
+            del self._sigids[dev]
         del self._devices[dev.get_id()]
diff --git a/src/model/devices/network/wireless.py b/src/model/devices/network/wireless.py
index b2efb49..e8b64ff 100644
--- a/src/model/devices/network/wireless.py
+++ b/src/model/devices/network/wireless.py
@@ -15,88 +15,16 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-import gobject
-
 from model.devices import device
 
-def freq_to_channel(freq):
-    ftoc = { 2.412: 1, 2.417: 2, 2.422: 3, 2.427: 4,
-	     2.432: 5, 2.437: 6, 2.442: 7, 2.447: 8,
-	     2.452: 9, 2.457: 10, 2.462: 11, 2.467: 12,
-	     2.472: 13
-	     }
-    return ftoc[freq]
-
-def channel_to_freq(channel):
-    ctof = { 1: 2.412, 2: 2.417, 3: 2.422, 4: 2.427,
-	     5: 2.432, 6: 2.437, 7: 2.442, 8: 2.447,
-	     9: 2.452, 10: 2.457, 11: 2.462, 12: 2.467,
-	     13: 2.472
-	     }
-    return ctof[channel]
-
 class Device(device.Device):
-    __gproperties__ = {
-        'name'     : (str, None, None, None,
-                      gobject.PARAM_READABLE),
-        'strength' : (int, None, None, 0, 100, 0,
-                      gobject.PARAM_READABLE),
-        'state'    : (int, None, None, device.STATE_ACTIVATING,
-                      device.STATE_INACTIVE, 0, gobject.PARAM_READABLE),
-        'frequency': (float, None, None, 0.0, 9999.99, 0.0,
-                      gobject.PARAM_READABLE),
-        'ip-address' : (str, None, None, None, gobject.PARAM_READABLE),
-    }
-
     def __init__(self, nm_device):
         device.Device.__init__(self)
-        self._nm_device = nm_device
-
-        self._nm_device.connect('strength-changed',
-                                self._strength_changed_cb)
-        self._nm_device.connect('ssid-changed',
-                                self._ssid_changed_cb)
-        self._nm_device.connect('state-changed',
-                                self._state_changed_cb)
-        self._nm_device.connect('ip-changed', self._ip_changed_cb)
-
-    def _strength_changed_cb(self, nm_device):
-        self.notify('strength')
-
-    def _ssid_changed_cb(self, nm_device):
-        self.notify('name')
-
-    def _state_changed_cb(self, nm_device):
-        self.notify('state')
-
-    def _ip_changed_cb(self, nm_device):
-        self.notify('ip-address')
-
-    def do_get_property(self, pspec):
-        if pspec.name == 'strength':
-            return self._nm_device.get_strength()
-        elif pspec.name == 'name':
-            import logging
-            logging.debug('wireless.Device.props.name: %s' %
-                    self._nm_device.get_ssid())
-            return self._nm_device.get_ssid()
-        elif pspec.name == 'state':
-            nm_state = self._nm_device.get_state()
-            return device.nm_state_to_state[nm_state]
-        elif pspec.name == 'frequency':
-            return self._nm_device.get_frequency()
-        elif pspec.name == 'ip-address':
-            return self._nm_device.get_ip_address()
+        self.nm_device = nm_device
 
     def get_type(self):
         return 'network.wireless'
 
     def get_id(self):
-        return str(self._nm_device.get_op())
-
-    def get_active_network_colors(self):
-        net = self._nm_device.get_active_network()
-        if not net:
-            return (None, None)
-        return net.get_colors()
+        return str(self.nm_device.object_path)
 
diff --git a/src/model/neighborhood.py b/src/model/neighborhood.py
new file mode 100644
index 0000000..0a09a62
--- /dev/null
+++ b/src/model/neighborhood.py
@@ -0,0 +1,168 @@
+# Copyright (C) 2006-2007 Red Hat, Inc.
+#
+# 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+
+import gobject
+
+from sugar.graphics.xocolor import XoColor
+from sugar.presence import presenceservice
+from sugar import activity
+
+from model.BuddyModel import BuddyModel
+
+class ActivityModel:
+    def __init__(self, act, bundle):
+        self.activity = act
+        self.bundle = bundle
+
+    def get_id(self):
+        return self.activity.props.id
+        
+    def get_icon_name(self):
+        return self.bundle.icon
+    
+    def get_color(self):
+        return XoColor(self.activity.props.color)
+
+    def get_bundle_id(self):
+        return self.bundle.bundle_id
+
+class Neighborhood(gobject.GObject):
+    __gsignals__ = {
+        'activity-added':       (gobject.SIGNAL_RUN_FIRST,
+                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
+        'activity-removed':     (gobject.SIGNAL_RUN_FIRST,
+                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
+        'buddy-added':          (gobject.SIGNAL_RUN_FIRST,
+                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
+        'buddy-moved':          (gobject.SIGNAL_RUN_FIRST,
+                                 gobject.TYPE_NONE,
+                                ([gobject.TYPE_PYOBJECT,
+                                  gobject.TYPE_PYOBJECT])),
+        'buddy-removed':        (gobject.SIGNAL_RUN_FIRST,
+                                 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT]))
+    }
+
+    def __init__(self):
+        gobject.GObject.__init__(self)
+
+        self._activities = {}
+        self._buddies = {}
+
+        self._pservice = presenceservice.get_instance()
+        self._pservice.connect("activity-appeared",
+                               self._activity_appeared_cb)
+        self._pservice.connect('activity-disappeared',
+                               self._activity_disappeared_cb)
+        self._pservice.connect("buddy-appeared",
+                               self._buddy_appeared_cb)
+        self._pservice.connect("buddy-disappeared",
+                               self._buddy_disappeared_cb)
+
+        # Add any buddies the PS knows about already
+        self._pservice.get_buddies_async(reply_handler=self._get_buddies_cb)
+
+        self._pservice.get_activities_async(
+                reply_handler=self._get_activities_cb)
+
+    def _get_buddies_cb(self, buddy_list):
+        for buddy in buddy_list:
+            self._buddy_appeared_cb(self._pservice, buddy)
+
+    def _get_activities_cb(self, activity_list):
+        for act in activity_list:
+            self._check_activity(act)
+
+    def get_activities(self):
+        return self._activities.values()
+
+    def get_buddies(self):
+        return self._buddies.values()
+
+    def _buddy_activity_changed_cb(self, model, cur_activity):
+        if not self._buddies.has_key(model.get_key()):
+            return
+        if cur_activity and self._activities.has_key(cur_activity.props.id):
+            activity_model = self._activities[cur_activity.props.id]
+            self.emit('buddy-moved', model, activity_model)
+        else:
+            self.emit('buddy-moved', model, None)
+
+    def _buddy_appeared_cb(self, pservice, buddy):
+        if self._buddies.has_key(buddy.props.key):
+            return
+
+        model = BuddyModel(buddy=buddy)
+        model.connect('current-activity-changed',
+                      self._buddy_activity_changed_cb)
+        self._buddies[buddy.props.key] = model
+        self.emit('buddy-added', model)
+
+        cur_activity = buddy.props.current_activity
+        if cur_activity:
+            self._buddy_activity_changed_cb(model, cur_activity)
+
+    def _buddy_disappeared_cb(self, pservice, buddy):
+        if not self._buddies.has_key(buddy.props.key):
+            return
+        self.emit('buddy-removed', self._buddies[buddy.props.key])
+        del self._buddies[buddy.props.key]
+
+    def _activity_appeared_cb(self, pservice, act):
+        self._check_activity(act)
+
+    def _check_activity(self, presence_activity):
+        registry = activity.get_registry()
+        bundle = registry.get_activity(presence_activity.props.type)
+        if not bundle:
+            return
+        if self.has_activity(presence_activity.props.id):
+            return
+        self.add_activity(bundle, presence_activity)
+
+    def has_activity(self, activity_id):
+        return self._activities.has_key(activity_id)
+
+    def get_activity(self, activity_id):
+        if self.has_activity(activity_id):
+            return self._activities[activity_id]
+        else:
+            return None
+
+    def add_activity(self, bundle, act):
+        model = ActivityModel(act, bundle)
+        self._activities[model.get_id()] = model
+        self.emit('activity-added', model)
+
+        for buddy in self._pservice.get_buddies():
+            cur_activity = buddy.props.current_activity
+            key = buddy.props.key
+            if cur_activity == activity and self._buddies.has_key(key):
+                buddy_model = self._buddies[key]
+                self.emit('buddy-moved', buddy_model, model)
+
+    def _activity_disappeared_cb(self, pservice, act):
+        if self._activities.has_key(act.props.id):
+            activity_model = self._activities[act.props.id]
+            self.emit('activity-removed', activity_model)
+            del self._activities[act.props.id]
+
+_model = None
+
+def get_model():
+    global _model
+    if _model is None:
+        _model = Neighborhood()
+    return _model
diff --git a/src/model/network.py b/src/model/network.py
new file mode 100644
index 0000000..d793deb
--- /dev/null
+++ b/src/model/network.py
@@ -0,0 +1,363 @@
+# Copyright (C) 2008 Red Hat, Inc.
+#
+# 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+
+import logging
+import os
+
+import dbus
+import ConfigParser
+
+from sugar import dispatch
+from sugar import env
+
+DEVICE_TYPE_802_11_WIRELESS = 2
+
+DEVICE_STATE_UNKNOWN = 0
+DEVICE_STATE_UNMANAGED = 1
+DEVICE_STATE_UNAVAILABLE = 2
+DEVICE_STATE_DISCONNECTED = 3
+DEVICE_STATE_PREPARE = 4
+DEVICE_STATE_CONFIG = 5
+DEVICE_STATE_NEED_AUTH = 6
+DEVICE_STATE_IP_CONFIG = 7
+DEVICE_STATE_ACTIVATED = 8
+DEVICE_STATE_FAILED = 9
+
+NM_802_11_AP_FLAGS_NONE = 0x00000000
+NM_802_11_AP_FLAGS_PRIVACY = 0x00000001
+
+NM_802_11_AP_SEC_NONE = 0x00000000
+NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001
+NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002
+NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004
+NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008
+NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010
+NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020
+NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040
+NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080
+NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100
+NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200
+
+NM_802_11_MODE_UNKNOWN = 0
+NM_802_11_MODE_ADHOC = 1
+NM_802_11_MODE_INFRA = 2
+
+NM_802_11_DEVICE_CAP_NONE = 0x00000000
+NM_802_11_DEVICE_CAP_CIPHER_WEP40 = 0x00000001
+NM_802_11_DEVICE_CAP_CIPHER_WEP104 = 0x00000002
+NM_802_11_DEVICE_CAP_CIPHER_TKIP = 0x00000004
+NM_802_11_DEVICE_CAP_CIPHER_CCMP = 0x00000008
+NM_802_11_DEVICE_CAP_WPA = 0x00000010
+NM_802_11_DEVICE_CAP_RSN = 0x00000020
+
+SETTINGS_SERVICE = 'org.freedesktop.NetworkManagerUserSettings'
+
+NM_SETTINGS_PATH = '/org/freedesktop/NetworkManagerSettings'
+NM_SETTINGS_IFACE = 'org.freedesktop.NetworkManagerSettings'
+NM_CONNECTION_IFACE = 'org.freedesktop.NetworkManagerSettings.Connection'
+NM_SECRETS_IFACE = 'org.freedesktop.NetworkManagerSettings.Connection.Secrets'
+
+_nm_settings = None
+_conn_counter = 0
+
+class WirelessSecurity(object):
+    def __init__(self):
+        self.key_mgmt = None
+        self.proto = None
+        self.group = None
+        self.pairwise = None
+
+    def get_dict(self):
+        wireless_security = {}
+
+        if self.key_mgmt is not None:
+            wireless_security['key-mgmt'] = self.key_mgmt
+        if self.proto is not None:
+            wireless_security['proto'] = self.proto
+        if self.pairwise is not None:
+            wireless_security['pairwise'] = self.pairwise
+        if self.group is not None:
+            wireless_security['group'] = self.group
+
+        return wireless_security
+
+class Wireless(object):
+    def __init__(self):
+        self.ssid = None
+
+    def get_dict(self):
+        return {'ssid': self.ssid}
+
+class Connection(object):
+    def __init__(self):
+        self.id = None
+        self.uuid = None
+        self.type = None
+
+    def get_dict(self):
+        return {'id': self.id,
+                'uuid': self.uuid,
+                'type': self.type}
+
+class Settings(object):
+    def __init__(self):
+        self.connection = Connection()
+        self.wireless = Wireless()
+        self.wireless_security = None
+
+    def get_dict(self):
+        settings = {}
+        settings['connection'] = self.connection.get_dict()
+        settings['802-11-wireless'] = self.wireless.get_dict()
+        if self.wireless_security is not None:
+            settings['802-11-wireless-security'] = \
+                self.wireless_security.get_dict()
+        return settings
+
+class Secrets(object):
+    def __init__(self):
+        self.wep_key = None
+        self.psk = None
+        self.auth_alg = None
+
+    def get_dict(self):
+        secrets = {}
+
+        if self.wep_key is not None:
+            secrets['wep-key0'] = self.wep_key
+        if self.psk is not None:
+            secrets['psk'] = self.psk
+        if self.auth_alg is not None:
+            secrets['auth-alg'] = self.auth_alg
+
+        return {'802-11-wireless-security': secrets}
+
+class NMSettings(dbus.service.Object):
+    def __init__(self):
+        bus = dbus.SystemBus()
+        bus_name = dbus.service.BusName(SETTINGS_SERVICE, bus=bus)
+        dbus.service.Object.__init__(self, bus_name, NM_SETTINGS_PATH)
+
+        self.connections = {}
+        self.secrets_request = dispatch.Signal()
+
+    @dbus.service.method(dbus_interface=NM_SETTINGS_IFACE,
+                         in_signature='', out_signature='ao')
+    def ListConnections(self):
+        return self.connections.values()
+
+    @dbus.service.signal(NM_SETTINGS_IFACE, signature='o')
+    def NewConnection(self, connection_path):
+        pass
+
+    def add_connection(self, ssid, conn):
+        self.connections[ssid] = conn
+        conn.secrets_request.connect(self.__secrets_request_cb)
+        self.NewConnection(conn.path)
+
+    def __secrets_request_cb(self, sender, **kwargs):
+        self.secrets_request.send(self, connection=sender,
+                                  response=kwargs['response'])
+
+class SecretsResponse(object):
+    ''' Intermediate object to report the secrets from the dialog
+    back to the connection object and which will inform NM
+    '''
+    def __init__(self, connection, reply_cb, error_cb):
+        self._connection = connection
+        self._reply_cb = reply_cb
+        self._error_cb = error_cb
+
+    def set_secrets(self, secrets):
+        self._connection.set_secrets(secrets)
+        self._reply_cb(secrets.get_dict())
+
+    def set_error(self, error):
+        self._error_cb(error)
+
+class NMSettingsConnection(dbus.service.Object):
+    def __init__(self, path, settings, secrets):
+        bus = dbus.SystemBus()
+        bus_name = dbus.service.BusName(SETTINGS_SERVICE, bus=bus)
+        dbus.service.Object.__init__(self, bus_name, path)
+
+        self.path = path
+        self.secrets_request = dispatch.Signal()
+
+        self._settings = settings
+        self._secrets = secrets
+
+    def set_secrets(self, secrets):
+        self._secrets = secrets
+        self.save()
+
+    def save(self):
+        profile_path = env.get_profile_path()
+        config_path = os.path.join(profile_path, 'nm', 'connections.cfg')
+
+        config = ConfigParser.ConfigParser()
+        try:
+            try:
+                if not config.read(config_path):
+                    logging.error('Error reading the nm config file')
+                    return
+            except ConfigParser.ParsingError, e:
+                logging.error('Error reading the nm config file: %s' % e)
+                return
+            identifier = self._settings.connection.id
+
+            if identifier not in config.sections():
+                config.add_section(identifier)
+            config.set(identifier, 'type', self._settings.connection.type)
+            config.set(identifier, 'ssid', self._settings.wireless.ssid)
+            config.set(identifier, 'uuid', self._settings.connection.uuid)
+
+            if self._settings.wireless_security is not None:
+                if self._settings.wireless_security.key_mgmt is not None:
+                    config.set(identifier, 'key-mgmt',
+                               self._settings.wireless_security.key_mgmt)
+                if self._settings.wireless_security.proto is not None:
+                    config.set(identifier, 'proto',
+                               self._settings.wireless_security.proto)
+                if self._settings.wireless_security.pairwise is not None:
+                    config.set(identifier, 'pairwise',
+                               self._settings.wireless_security.pairwise)
+                if self._settings.wireless_security.group is not None:
+                    config.set(identifier, 'group',
+                               self._settings.wireless_security.group)
+            if self._secrets is not None:
+                if self._settings.wireless_security.key_mgmt == 'none':
+                    config.set(identifier, 'key', self._secrets.wep_key)
+                    config.set(identifier, 'auth-alg', self._secrets.auth_alg)
+                elif self._settings.wireless_security.key_mgmt == 'wpa-psk':
+                    config.set(identifier, 'key', self._secrets.psk)
+        except ConfigParser.Error, e:
+            logging.error('Error constructing %s: %s' % (identifier, e))
+        else:
+            f = open(config_path, 'w')
+            try:
+                config.write(f)
+            except ConfigParser.Error, e:
+                logging.error('Can not write %s error: %s' % (config_path, e))
+            f.close()
+
+    @dbus.service.method(dbus_interface=NM_CONNECTION_IFACE,
+                         in_signature='', out_signature='a{sa{sv}}')
+    def GetSettings(self):
+        return self._settings.get_dict()
+
+    @dbus.service.method(dbus_interface=NM_SECRETS_IFACE,
+                         async_callbacks=('reply', 'error'),
+                         in_signature='sasb', out_signature='a{sa{sv}}')
+    def GetSecrets(self, setting_name, hints, request_new, reply, error):
+        logging.debug('Secrets requested for connection %s request_new=%s'
+                      % (self.path, request_new))
+
+        if request_new or self._secrets is None:
+            # request_new is for example the case when the pw on the AP changes
+            response = SecretsResponse(self, reply, error)
+            try:
+                self.secrets_request.send(self, response=response)
+            except Exception, e:
+                logging.error('Error requesting the secrets via dialog: %s' % e)
+        else:
+            reply(self._secrets.get_dict())
+
+def get_settings():
+    global _nm_settings
+    if _nm_settings is None:
+        try:
+            _nm_settings = NMSettings()
+        except dbus.DBusException, e:
+            logging.error('Cannot create the UserSettings service %s.', e)
+        load_connections()
+    return _nm_settings
+
+def find_connection(ssid):
+    connections = get_settings().connections
+    if ssid in connections:
+        return connections[ssid]
+    else:
+        return None
+
+def add_connection(ssid, settings, secrets=None):
+    global _conn_counter
+
+    path = NM_SETTINGS_PATH + '/' + str(_conn_counter)
+    _conn_counter += 1
+
+    conn = NMSettingsConnection(path, settings, secrets)
+    _nm_settings.add_connection(ssid, conn)
+    return conn
+
+def load_connections():
+    profile_path = env.get_profile_path()
+    config_path = os.path.join(profile_path, 'nm', 'connections.cfg')
+
+    config = ConfigParser.ConfigParser()
+
+    if not os.path.exists(config_path):
+        if not os.path.exists(os.path.dirname(config_path)):
+            os.makedirs(os.path.dirname(config_path), 0755)
+        f = open(config_path, 'w')
+        config.write(f)
+        f.close()
+
+    try:
+        if not config.read(config_path):
+            logging.error('Error reading the nm config file')
+            return
+    except ConfigParser.ParsingError, e:
+        logging.error('Error reading the nm config file: %s' % e)
+        return
+
+    for section in config.sections():
+        try:
+            settings = Settings()
+            settings.connection.id = section
+            ssid = config.get(section, 'ssid')
+            settings.wireless.ssid = dbus.ByteArray(ssid)
+            uuid = config.get(section, 'uuid')
+            settings.connection.uuid = uuid
+            nmtype = config.get(section, 'type')
+            settings.connection.type = nmtype
+
+            secrets = None
+            if config.has_option(section, 'key-mgmt'):
+                secrets = Secrets()
+                settings.wireless_security = WirelessSecurity()
+                mgmt = config.get(section, 'key-mgmt')
+                settings.wireless_security.key_mgmt = mgmt
+                key = config.get(section, 'key')
+                if mgmt == 'none':
+                    secrets.wep_key = key
+                    auth_alg = config.get(section, 'auth-alg')
+                    secrets.auth_alg = auth_alg
+                elif mgmt == 'wpa-psk':
+                    secrets.psk = key
+                    if config.has_option(section, 'proto'):
+                        value = config.get(section, 'proto')
+                        settings.wireless_security.proto = value
+                    if config.has_option(section, 'group'):
+                        value = config.get(section, 'group')
+                        settings.wireless_security.group = value
+                    if config.has_option(section, 'pairwise'):
+                        value = config.get(section, 'pairwise')
+                        settings.wireless_security.pairwise = value
+        except ConfigParser.Error, e:
+            logging.error('Error reading section: %s' % e)
+        else:
+            add_connection(ssid, settings, secrets)
diff --git a/src/model/shellmodel.py b/src/model/shellmodel.py
index d1d8db8..7e786be 100644
--- a/src/model/shellmodel.py
+++ b/src/model/shellmodel.py
@@ -19,7 +19,6 @@ import gobject
 
 from sugar.presence import presenceservice
 from model.Friends import Friends
-from model.MeshModel import MeshModel
 from model.homemodel import HomeModel
 from model.Owner import ShellOwner
 from model.devices.devicesmodel import DevicesModel
@@ -48,7 +47,6 @@ class ShellModel(gobject.GObject):
         self._owner = ShellOwner()
 
         self._friends = Friends()
-        self._mesh = MeshModel()
         self._home = HomeModel()
         self._devices = DevicesModel()
 
@@ -70,9 +68,6 @@ class ShellModel(gobject.GObject):
         if pspec.name == 'zoom-level':
             return self.get_zoom_level()                
 
-    def get_mesh(self):
-        return self._mesh
-
     def get_friends(self):
         return self._friends
 
diff --git a/src/view/devices/network/wireless.py b/src/view/devices/network/wireless.py
index 5bef0bb..a9cf22b 100644
--- a/src/view/devices/network/wireless.py
+++ b/src/view/devices/network/wireless.py
@@ -16,19 +16,19 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 from gettext import gettext as _
+import logging
+import sha
 
 import gtk
+import dbus
 
 from sugar.graphics.icon import get_icon_state
 from sugar.graphics import style
 from sugar.graphics.palette import Palette
 from sugar.graphics.toolbutton import ToolButton
-from sugar.graphics.xocolor import XoColor
+from sugar.graphics import xocolor
 
-from model.devices.network import wireless
-from model.devices import device
-from hardware import hardwaremanager
-from hardware import nmclient
+from model import network
 from view.frame.frameinvoker import FrameWidgetInvoker
 from view.pulsingicon import PulsingIcon
 
@@ -36,109 +36,38 @@ _ICON_NAME = 'network-wireless'
 
 IP_ADDRESS_TEXT_TEMPLATE = _("IP address: %s")
 
-class DeviceView(ToolButton):
-
-    FRAME_POSITION_RELATIVE = 300
-
-    def __init__(self, model):
-        ToolButton.__init__(self)
-        self._model = model
-
-        self._icon = PulsingIcon()
-        self._icon.props.icon_name = _ICON_NAME
-        pulse_color = XoColor("%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(),
-                                         style.COLOR_TRANSPARENT.get_svg()))
-        self._icon.props.pulse_color = pulse_color
-        self._icon.props.base_color = pulse_color   # only temporarily
-        self._inactive_color = XoColor("%s,%s" % (
-                style.COLOR_INACTIVE_STROKE.get_html(),
-                style.COLOR_INACTIVE_FILL.get_html()))
-
-        meshdev = None
-        network_manager = hardwaremanager.get_network_manager()
-        for dev in network_manager.get_devices():
-            if dev.get_type() == nmclient.DEVICE_TYPE_802_11_MESH_OLPC:
-                meshdev = dev
-                break
-
-        self._counter = 0
-        self.palette = WirelessPalette(self._get_palette_primary_text(),
-                                       meshdev)
-        self.set_palette(self.palette)
-        self.palette.props.invoker = FrameWidgetInvoker(self)
-        self.palette.set_group_id('frame')
-        self.palette.set_frequency(self._model.props.frequency)
-
-        model.connect('notify::name', self._name_changed_cb)
-        model.connect('notify::ip-address', self._ip_address_changed_cb)
-        model.connect('notify::strength', self._strength_changed_cb)
-        model.connect('notify::state', self._state_changed_cb)
-
-        self._update_icon()
-        self._update_state()
-        self._update_ip_address()
-
-        self.set_icon_widget(self._icon)
-        self._icon.show()
-
-    def _get_palette_primary_text(self):
-        if self._model.props.state == device.STATE_INACTIVE:
-            return _("Disconnected")
-        return self._model.props.name
-
-    def _strength_changed_cb(self, model, pspec):
-        self._update_icon()
-        # Only update frequency periodically
-        if self._counter % 4 == 0:
-            self.palette.set_frequency(self._model.props.frequency)
-        self._counter += 1
-
-    def _ip_address_changed_cb(self, model, pspec):
-        self._update_ip_address()
-
-    def _name_changed_cb(self, model, pspec):
-        self.palette.set_primary_text(self._get_palette_primary_text())
-        self._update_state()
-
-    def _state_changed_cb(self, model, pspec):
-        self._update_icon()
-        self._update_state()
-        self.palette.set_primary_text(self._get_palette_primary_text())
-
-    def _update_icon(self):
-        # keep this code in sync with view/home/MeshBox.py
-        strength = self._model.props.strength
-        if self._model.props.state == device.STATE_INACTIVE:
-            strength = 0
-        if self._model.props.state == device.STATE_ACTIVATED:
-            icon_name = '%s-connected' % _ICON_NAME
-        else:
-            icon_name = _ICON_NAME
-        icon_name = get_icon_state(icon_name, strength)
-        if icon_name:
-            self._icon.props.icon_name = icon_name
-
-    def _update_state(self):
-        # FIXME Change icon colors once we have real icons
-        state = self._model.props.state
-        self._icon.props.pulsing = state == device.STATE_ACTIVATING
-        if state == device.STATE_ACTIVATING:
-            fill = style.COLOR_INACTIVE_FILL.get_svg()
-            stroke = style.COLOR_INACTIVE_STROKE.get_svg()
-        elif state == device.STATE_ACTIVATED:
-            (stroke, fill) = self._model.get_active_network_colors()
-        elif state == device.STATE_INACTIVE:
-            fill = style.COLOR_INACTIVE_FILL.get_svg()
-            stroke = style.COLOR_INACTIVE_STROKE.get_svg()
-        self._icon.props.base_color = XoColor("%s,%s" % (stroke, fill))
-
-    def _update_ip_address(self):
-        self.palette.set_ip_address(self._model.props.ip_address)
+_NM_SERVICE = 'org.freedesktop.NetworkManager'
+_NM_IFACE = 'org.freedesktop.NetworkManager'
+_NM_PATH = '/org/freedesktop/NetworkManager'
+_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device'
+_NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless'
+_NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint'
+_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active'
+
+_NM_DEVICE_STATE_UNKNOWN = 0
+_NM_DEVICE_STATE_UNMANAGED = 1
+_NM_DEVICE_STATE_UNAVAILABLE = 2
+_NM_DEVICE_STATE_DISCONNECTED = 3
+_NM_DEVICE_STATE_PREPARE = 4
+_NM_DEVICE_STATE_CONFIG = 5
+_NM_DEVICE_STATE_NEED_AUTH = 6
+_NM_DEVICE_STATE_IP_CONFIG = 7
+_NM_DEVICE_STATE_ACTIVATED = 8
+_NM_DEVICE_STATE_FAILED = 9
+
+def freq_to_channel(freq):
+    ftoc = { 2412: 1, 2417: 2, 2422: 3, 2427: 4,
+             2432: 5, 2437: 6, 2442: 7, 2447: 8,
+             2452: 9, 2457: 10, 2462: 11, 2467: 12,
+             2472: 13}
+    return ftoc[freq]
 
 class WirelessPalette(Palette):
-    def __init__(self, primary_text, meshdev):
-        Palette.__init__(self, primary_text, menu_after_content=True)
-        self._meshdev = meshdev
+    def __init__(self, primary_text, device_view):
+        Palette.__init__(self, label=primary_text)
+
+        self._device_view = device_view
+        self._disconnect_item = None
 
         self._chan_label = gtk.Label()
         self._chan_label.props.xalign = 0.0
@@ -146,7 +75,7 @@ class WirelessPalette(Palette):
 
         self._ip_address_label = gtk.Label()
 
-        vbox = gtk.VBox()
+        self._info = gtk.VBox()
 
         def _padded(child, xalign=0, yalign=0.5):
             padder = gtk.Alignment(xalign=xalign, yalign=yalign,
@@ -158,34 +87,228 @@ class WirelessPalette(Palette):
             padder.add(child)
             return padder
 
-        vbox.pack_start(_padded(self._chan_label))
-        vbox.pack_start(_padded(self._ip_address_label))
-        vbox.show_all()
+        self._info.pack_start(_padded(self._chan_label))
+        self._info.pack_start(_padded(self._ip_address_label))
+        self._info.show_all()
+
+        self._disconnect_item = gtk.MenuItem(_('Disconnect...'))
+        self._disconnect_item.connect('activate', self._disconnect_activate_cb)
+        self.menu.append(self._disconnect_item)
+
+        self.disconnected()
 
-        if meshdev:
-            disconnect_item = gtk.MenuItem(_('Disconnect...'))
-            disconnect_item.connect('activate', self._disconnect_activate_cb)
-            self.menu.append(disconnect_item)
-            disconnect_item.show()
+    def connecting(self):
+        self.props.secondary_text = _('Connecting...')
 
-        self.set_content(vbox)
+    def connected(self, frequency, iaddress):
+        self.set_content(self._info)
+        self.props.secondary_text = _('Connected')
+        self._set_channel(frequency)
+        self._set_ip_address(iaddress)
+        self._disconnect_item.show()
+
+    def disconnected(self):
+        self.props.primary_text = ''
+        self.props.secondary_text = _('Not connected')
+        self.set_content(None)
+        self._disconnect_item.hide()
 
     def _disconnect_activate_cb(self, menuitem):
-        # Disconnection for an AP means activating the default mesh device
-        network_manager = hardwaremanager.get_network_manager()
-        if network_manager and self._meshdev:
-            network_manager.set_active_device(self._meshdev)
+        self._device_view.deactivate_connection()
+
+    def _inet_ntoa(self, iaddress):
+        address = ['%s' % ((iaddress >> i) % 256) for i in [0, 8, 16, 24]]
+        return ".".join(address)
 
-    def set_frequency(self, freq):
+    def _set_channel(self, freq):
         try:
-            chan = wireless.freq_to_channel(freq)
+            chan = freq_to_channel(freq)
         except KeyError:
             chan = 0
         self._chan_label.set_text("%s: %d" % (_("Channel"), chan))
 
-    def set_ip_address(self, ip_address):
-        if ip_address is not None and ip_address != "0.0.0.0":
-            ip_address_text = IP_ADDRESS_TEXT_TEMPLATE % ip_address
+    def _set_ip_address(self, ip_address):
+        if ip_address is not None:
+            ip_address_text = IP_ADDRESS_TEXT_TEMPLATE % \
+                self._inet_ntoa(ip_address)
         else:
             ip_address_text = ""
         self._ip_address_label.set_text(ip_address_text)
+
+
+class DeviceView(ToolButton):
+
+    FRAME_POSITION_RELATIVE = 300
+
+    def __init__(self, device):
+        ToolButton.__init__(self)
+
+        self._bus = dbus.SystemBus()
+        self._device = device.nm_device
+        self._flags = 0
+        self._name = ''
+        self._strength = 0
+        self._frequency = 0
+        self._device_state = None
+        self._color = None
+        self._active_ap_op = None
+
+        self._icon = PulsingIcon()
+        self._icon.props.icon_name = get_icon_state(_ICON_NAME, 0)
+        self._inactive_color = xocolor.XoColor( \
+            "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(),
+                       style.COLOR_TRANSPARENT.get_svg()))
+        self._icon.props.pulse_color = self._inactive_color
+        self._icon.props.base_color = self._inactive_color
+
+        self.set_icon_widget(self._icon)
+        self._icon.show()
+
+        self._palette = WirelessPalette(self._name, self)
+        self.set_palette(self._palette)
+        self._palette.props.invoker = FrameWidgetInvoker(self)
+        self._palette.set_group_id('frame')
+
+        self._device.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint',
+                         reply_handler=self.__get_active_ap_reply_cb,
+                         error_handler=self.__get_active_ap_error_cb)
+
+        self._bus.add_signal_receiver(self.__state_changed_cb,
+                                      signal_name='StateChanged',
+                                      path=self._device.object_path,
+                                      dbus_interface=_NM_DEVICE_IFACE)
+
+    def disconnect(self):
+        self._bus.remove_signal_receiver(self.__state_changed_cb,
+                                         signal_name='StateChanged',
+                                         path=self._device.object_path,
+                                         dbus_interface=_NM_DEVICE_IFACE)
+
+    def __get_active_ap_reply_cb(self, active_ap_op):
+        if self._active_ap_op != active_ap_op:
+            if self._active_ap_op is not None:
+                self._bus.remove_signal_receiver(
+                    self.__ap_properties_changed_cb,
+                    signal_name='PropertiesChanged',
+                    path=self._active_ap_op,
+                    dbus_interface=_NM_ACCESSPOINT_IFACE)
+            if active_ap_op == '/':
+                self._active_ap_op = None
+                return
+            self._active_ap_op = active_ap_op
+            active_ap = self._bus.get_object(_NM_SERVICE, active_ap_op)
+            props = dbus.Interface(active_ap, 'org.freedesktop.DBus.Properties')
+
+            props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True,
+                         reply_handler=self.__get_all_props_reply_cb,
+                         error_handler=self.__get_all_props_error_cb)
+
+            self._bus.add_signal_receiver(self.__ap_properties_changed_cb,
+                                          signal_name='PropertiesChanged',
+                                          path=self._active_ap_op,
+                                          dbus_interface=_NM_ACCESSPOINT_IFACE)
+
+    def __get_active_ap_error_cb(self, err):
+        logging.debug('Error getting the active access point: %s', err)
+
+    def __state_changed_cb(self, new_state, old_state, reason):
+        self._device_state = new_state
+        self._update_state()
+
+        self._device.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint',
+                         reply_handler=self.__get_active_ap_reply_cb,
+                         error_handler=self.__get_active_ap_error_cb)
+
+    def __ap_properties_changed_cb(self, properties):
+        self._update_properties(properties)
+
+    def _update_properties(self, properties):
+        if 'Ssid' in properties:
+            self._name = properties['Ssid']
+        if 'Strength' in properties:
+            self._strength = properties['Strength']
+        if 'Flags' in properties:
+            self._flags = properties['Flags']
+        if 'Frequency' in properties:
+            self._frequency = properties['Frequency']
+
+        sh = sha.new()
+        data = self._name + hex(self._flags)
+        sh.update(data)
+        h = hash(sh.digest())
+        idx = h % len(xocolor.colors)
+
+        self._color = xocolor.XoColor('%s,%s' % (xocolor.colors[idx][0],
+                                                 xocolor.colors[idx][1]))
+        self._update()
+
+    def __get_all_props_reply_cb(self, properties):
+        self._update_properties(properties)
+
+    def __get_all_props_error_cb(self, err):
+        logging.debug('Error getting the access point properties: %s', err)
+
+    def _update(self):
+        if self._flags == network.NM_802_11_AP_FLAGS_PRIVACY:
+            self._icon.props.badge_name = "emblem-locked"
+        else:
+            self._icon.props.badge_name = None
+
+        self._palette.props.primary_text = self._name
+
+        self._update_state()
+        self._update_color()
+
+    def _update_state(self):
+        if self._active_ap_op is not None:
+            state = self._device_state
+        else:
+            state = network.DEVICE_STATE_UNKNOWN
+
+        if state == network.DEVICE_STATE_ACTIVATED:
+            icon_name = '%s-connected' % _ICON_NAME
+        else:
+            icon_name = _ICON_NAME
+
+        icon_name = get_icon_state(icon_name, self._strength)
+        if icon_name:
+            self._icon.props.icon_name = icon_name
+
+        if state == network.DEVICE_STATE_PREPARE or \
+           state == network.DEVICE_STATE_CONFIG or \
+           state == network.DEVICE_STATE_NEED_AUTH or \
+           state == network.DEVICE_STATE_IP_CONFIG:
+            self._palette.connecting()
+            self._icon.props.pulsing = True
+        elif state == network.DEVICE_STATE_ACTIVATED:
+            props = dbus.Interface(self._device,
+                                   'org.freedesktop.DBus.Properties')
+            address = props.Get(_NM_DEVICE_IFACE, 'Ip4Address')
+            self._palette.connected(self._frequency, address)
+            self._icon.props.pulsing = False
+        else:
+            self._palette.disconnected()
+            self._icon.props.pulsing = False
+            self._icon.props.base_color = self._inactive_color
+            self._icon.props.badge_name = None
+            self._name = ''
+
+    def _update_color(self):
+        self._icon.props.base_color = self._color
+
+    def deactivate_connection(self):
+        if self._active_ap_op is not None:
+            obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
+            netmgr = dbus.Interface(obj, _NM_IFACE)
+            netmgr_props = dbus.Interface(
+                netmgr, 'org.freedesktop.DBus.Properties')
+            active_connections_o = netmgr_props.Get(_NM_IFACE,
+                                                    'ActiveConnections')
+
+            for conn_o in active_connections_o:
+                obj = self._bus.get_object(_NM_IFACE, conn_o)
+                props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
+                ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject')
+                if ap_op == self._active_ap_op:
+                    netmgr.DeactivateConnection(conn_o)
+                    break
diff --git a/src/view/home/Makefile.am b/src/view/home/Makefile.am
index b323589..9e4a754 100644
--- a/src/view/home/Makefile.am
+++ b/src/view/home/Makefile.am
@@ -7,6 +7,7 @@ sugar_PYTHON =			\
 	grid.py			\
 	FriendView.py		\
 	FriendsBox.py		\
+	keydialog.py		\
 	HomeBox.py		\
 	HomeWindow.py		\
 	MeshBox.py		\
diff --git a/src/view/home/MeshBox.py b/src/view/home/MeshBox.py
index 8cf8af6..568e1b9 100644
--- a/src/view/home/MeshBox.py
+++ b/src/view/home/MeshBox.py
@@ -16,254 +16,374 @@
 
 from gettext import gettext as _
 import logging
+import sha
 
+import dbus
 import hippo
 import gobject
 import gtk
 
 from sugar.graphics.icon import CanvasIcon, Icon
 from sugar.graphics.xocolor import XoColor
+from sugar.graphics import xocolor
 from sugar.graphics import style
 from sugar.graphics.icon import get_icon_state
 from sugar.graphics import palette
 from sugar.graphics import iconentry
 from sugar.graphics.menuitem import MenuItem
-from sugar import profile
+from sugar.util import unique_id
 
-from model import accesspointmodel
-from model.devices.network import wireless
-from model import shellmodel
-from hardware import hardwaremanager
-from hardware import nmclient
+from model import neighborhood
 from view.BuddyIcon import BuddyIcon
 from view.pulsingicon import CanvasPulsingIcon
 from view.home.snowflakelayout import SnowflakeLayout
 from view.home.spreadlayout import SpreadLayout
+from view.home import keydialog
+from model import network
+from model.network import Settings
+from model.network import WirelessSecurity
 import view.Shell
 
-from hardware.nmclient import NM_802_11_CAP_PROTO_WEP, \
-    NM_802_11_CAP_PROTO_WPA, NM_802_11_CAP_PROTO_WPA2
-
+_NM_SERVICE = 'org.freedesktop.NetworkManager'
+_NM_IFACE = 'org.freedesktop.NetworkManager'
+_NM_PATH = '/org/freedesktop/NetworkManager'
+_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device'
+_NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless'
+_NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint'
+_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active'
 
 _ICON_NAME = 'network-wireless'
 
 class AccessPointView(CanvasPulsingIcon):
-    def __init__(self, model, mesh_device=None):
+    def __init__(self, device, model):
         CanvasPulsingIcon.__init__(self, size=style.STANDARD_ICON_SIZE,
                                    cache=True)
+        self._bus = dbus.SystemBus()
+        self._device = device
         self._model = model
-        self._meshdev = mesh_device
+        self._palette_icon = None
         self._disconnect_item = None
         self._connect_item = None
         self._greyed_out = False
+        self._name = ''
+        self._strength = 0
+        self._flags = 0
+        self._wpa_flags = 0
+        self._rsn_flags = 0
+        self._mode = 0
+        self._device_caps = 0
+        self._device_state = None
+        self._connection = None
+        self._active = True
+        self._color = None
 
         self.connect('activated', self._activate_cb)
 
-        model.connect('notify::strength', self._strength_changed_cb)
-        model.connect('notify::name', self._name_changed_cb)
-        model.connect('notify::state', self._state_changed_cb)
-
         pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
                                          style.COLOR_TRANSPARENT.get_svg()))
         self.props.pulse_color = pulse_color
 
-        # Update badge
-        caps = model.props.capabilities
-        if model.get_nm_network().is_favorite():
-            self.props.badge_name = "emblem-favorite"
-        elif (caps & NM_802_11_CAP_PROTO_WEP) or \
-                (caps & NM_802_11_CAP_PROTO_WPA) or \
-                (caps & NM_802_11_CAP_PROTO_WPA2):
-            self.props.badge_name = "emblem-locked"
-
         self._palette = self._create_palette()
         self.set_palette(self._palette)
 
-        self._update_icon()
-        self._update_name()
-        self._update_state()
+        model_props = dbus.Interface(model, 'org.freedesktop.DBus.Properties')
+        model_props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True,
+                           reply_handler=self.__get_all_props_reply_cb,
+                           error_handler=self.__get_all_props_error_cb)
+
+        self._bus.add_signal_receiver(self.__ap_properties_changed_cb,
+                                      signal_name='PropertiesChanged',
+                                      path=model.object_path,
+                                      dbus_interface=_NM_ACCESSPOINT_IFACE)
+
+        self._device.Get(_NM_DEVICE_IFACE, 'State',
+                         reply_handler=self.__get_device_state_reply_cb,
+                         error_handler=self.__get_device_state_error_cb)
+        self._device.Get(_NM_WIRELESS_IFACE, 'WirelessCapabilities',
+                         reply_handler=self.__get_device_caps_reply_cb,
+                         error_handler=self.__get_device_caps_error_cb)
+        self._device.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint',
+                         reply_handler=self.__get_active_ap_reply_cb,
+                         error_handler=self.__get_active_ap_error_cb)
+
+        self._bus.add_signal_receiver(self.__device_state_changed_cb,
+                                      signal_name='StateChanged',
+                                      path=device.object_path,
+                                      dbus_interface=_NM_DEVICE_IFACE)
+        self._bus.add_signal_receiver(self.__wireless_properties_changed_cb,
+                                      signal_name='PropertiesChanged',
+                                      path=device.object_path,
+                                      dbus_interface=_NM_WIRELESS_IFACE)
 
     def _create_palette(self):
-        icon_name = get_icon_state(_ICON_NAME, self._model.props.strength)
-        palette_icon = Icon(icon_name=icon_name,
-                            icon_size=style.STANDARD_ICON_SIZE,
-                            badge_name=self.props.badge_name)
-        ap_color = self._model.get_nm_network().get_colors()
-        palette_icon.props.xo_color = XoColor('%s,%s' % ap_color)
+        icon_name = get_icon_state(_ICON_NAME, self._strength)
+        self._palette_icon = Icon(icon_name=icon_name,
+                                  icon_size=style.STANDARD_ICON_SIZE,
+                                  badge_name=self.props.badge_name)
                                               
-        p = palette.Palette(primary_text=self._model.props.name,
-                            icon=palette_icon)
+        p = palette.Palette(primary_text=self._name,
+                            icon=self._palette_icon)
 
         self._connect_item = MenuItem(_('Connect'), 'dialog-ok')
         self._connect_item.connect('activate', self._activate_cb)
         p.menu.append(self._connect_item)
 
-        # Only show disconnect when there's a mesh device, because mesh takes
-        # priority over the normal wireless device. NM doesn't have a
-        # "disconnect" method for a device either (for various reasons)
-        # so this doesn't have a good mapping
-        if self._meshdev:
-            self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject')
-            self._disconnect_item.connect('activate',
-                                          self._disconnect_activate_cb)
-            p.menu.append(self._disconnect_item)
+        self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject')
+        self._disconnect_item.connect('activate',
+                                        self._disconnect_activate_cb)
+        p.menu.append(self._disconnect_item)
 
         return p
 
-    def _disconnect_activate_cb(self, menuitem):
-        # Disconnection for an AP means activating the default mesh device
-        network_manager = hardwaremanager.get_network_manager()
-        if network_manager and self._meshdev:
-            network_manager.set_active_device(self._meshdev)
-            self._palette.props.secondary_text = _('Disconnecting...')
-            self.props.pulsing = False
+    def __device_state_changed_cb(self, new_state, old_state, reason):
+        self._device_state = new_state
+        self._update_state()
+
+    def __ap_properties_changed_cb(self, properties):
+        self._update_properties(properties)
+
+    def __wireless_properties_changed_cb(self, properties):
+        if 'ActiveAccessPoint' in properties:
+            ap = properties['ActiveAccessPoint']
+            self._active = (ap == self._model.object_path)
+            self._update_state()
+
+    def _update_properties(self, properties):
+        if 'Ssid' in properties:
+            self._name = properties['Ssid']
+        if 'Strength' in properties:
+            self._strength = properties['Strength']
+        if 'Flags' in properties:
+            self._flags = properties['Flags']
+        if 'WpaFlags' in properties:
+            self._wpa_flags = properties['WpaFlags']
+        if 'RsnFlags' in properties:
+            self._rsn_flags = properties['RsnFlags']
+        if 'Mode' in properties:
+            self._mode = properties['Mode']
+
+        sh = sha.new()
+        data = self._name + hex(self._flags)
+        sh.update(data)
+        h = hash(sh.digest())
+        idx = h % len(xocolor.colors)
+
+        self._color = XoColor('%s,%s' % (xocolor.colors[idx][0],
+                                         xocolor.colors[idx][1]))
+
+        self._update()
+
+    def __get_active_ap_reply_cb(self, ap):
+        self._active = (ap == self._model.object_path)
+        self._update_state()
+
+    def __get_active_ap_error_cb(self, err):
+        logging.debug('Error getting the active access point: %s', err)
+
+    def __get_device_caps_reply_cb(self, caps):
+        self._device_caps = caps
 
-    def _strength_changed_cb(self, model, pspec):
-        self._update_icon()
+    def __get_device_caps_error_cb(self, err):
+        logging.debug('Error getting the wireless device properties: %s', err)
 
-    def _name_changed_cb(self, model, pspec):
-        self._update_name()
+    def __get_device_state_reply_cb(self, state):
+        self._device_state = state
+        self._update()
+
+    def __get_device_state_error_cb(self, err):
+        logging.debug('Error getting the access point properties: %s', err)
+
+    def __get_all_props_reply_cb(self, properties):
+        self._update_properties(properties)
+
+    def __get_all_props_error_cb(self, err):
+        logging.debug('Error getting the access point properties: %s', err)
+
+    def _update(self):
+        if self._flags == network.NM_802_11_AP_FLAGS_PRIVACY:
+            self.props.badge_name = "emblem-locked"
+            self._palette_icon.props.badge_name = "emblem-locked"
+        else:
+            self.props.badge_name = None
+            self._palette_icon.props.badge_name = None
+
+        self._palette.props.primary_text = self._name
 
-    def _state_changed_cb(self, model, pspec):
-        self._update_icon()
         self._update_state()
+        self._update_color()
 
-    def _activate_cb(self, icon):
-        network_manager = hardwaremanager.get_network_manager()
-        if network_manager:
-            device = self._model.get_nm_device()
-            network = self._model.get_nm_network()
-            network_manager.set_active_device(device, network)
-
-    def _update_name(self):
-        self._palette.props.primary_text = self._model.props.name
-
-    def _update_icon(self):
-        # keep this code in sync with view/devices/network/wireless.py
-        strength = self._model.props.strength
-        if self._model.props.state == accesspointmodel.STATE_CONNECTED:
+    def _update_state(self):
+        if self._active:
+            state = self._device_state
+        else:
+            state = network.DEVICE_STATE_UNKNOWN
+
+        if state == network.DEVICE_STATE_ACTIVATED:
             icon_name = '%s-connected' % _ICON_NAME
         else:
             icon_name = _ICON_NAME
-        icon_name = get_icon_state(icon_name, strength)
+
+        icon_name = get_icon_state(icon_name, self._strength)
         if icon_name:
             self.props.icon_name = icon_name
             icon = self._palette.props.icon
             icon.props.icon_name = icon_name
 
-    def _update_state(self):
-        if self._model.props.state == accesspointmodel.STATE_CONNECTING:
+        if state == network.DEVICE_STATE_PREPARE or \
+           state == network.DEVICE_STATE_CONFIG or \
+           state == network.DEVICE_STATE_NEED_AUTH or \
+           state == network.DEVICE_STATE_IP_CONFIG:
             if self._disconnect_item:
                 self._disconnect_item.show()
             self._connect_item.hide()
             self._palette.props.secondary_text = _('Connecting...')
             self.props.pulsing = True
-        elif self._model.props.state == accesspointmodel.STATE_CONNECTED:
+        elif state == network.DEVICE_STATE_ACTIVATED:
             if self._disconnect_item:
                 self._disconnect_item.show()
             self._connect_item.hide()
-            # TODO: show the channel number
             self._palette.props.secondary_text = _('Connected')
             self.props.pulsing = False
-        elif self._model.props.state == accesspointmodel.STATE_NOTCONNECTED:
+        else:
             if self._disconnect_item:
                 self._disconnect_item.hide()
             self._connect_item.show()
-            # TODO: show the channel number
             self._palette.props.secondary_text = None
             self.props.pulsing = False
 
+    def _update_color(self):        
         if self._greyed_out:
             self.props.pulsing = False
             self.props.base_color = XoColor('#D5D5D5,#D5D5D5')
         else:
-            self.props.base_color = XoColor('%s,%s' % \
-                    self._model.get_nm_network().get_colors())
-
-    def set_filter(self, query):
-        self._greyed_out = self._model.props.name.lower().find(query) == -1
-        self._update_state()
-
-_MESH_ICON_NAME = 'network-mesh'
-
-class MeshDeviceView(CanvasPulsingIcon):
-    def __init__(self, nm_device, channel):
-        if not channel in [1, 6, 11]:
-            raise ValueError("Invalid channel %d" % channel)
-
-        CanvasPulsingIcon.__init__(self, size=style.STANDARD_ICON_SIZE,
-                             icon_name=_MESH_ICON_NAME, cache=True)
-
-        self._nm_device = nm_device
-        self.channel = channel
-        self.props.badge_name = "badge-channel-%d" % self.channel
-        self._greyed_out = False
+            self.props.base_color = self._color
 
-        self._disconnect_item = None
-        self._palette = self._create_palette()
-        self.set_palette(self._palette)
+        self._palette_icon.props.xo_color = self._color
 
-        pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
-                                         style.COLOR_TRANSPARENT.get_svg()))
-        self.props.pulse_color = pulse_color
+    def _disconnect_activate_cb(self, item):
+        pass
 
-        self.connect('activated', self._activate_cb)
 
-        self._nm_device.connect('state-changed', self._state_changed_cb)
-        self._nm_device.connect('activation-stage-changed',
-                                self._state_changed_cb)
-        self._update_state()
+    def _add_ciphers_from_flags(self, flags, pairwise):
+        ciphers = []
+        if pairwise:
+            if flags & network.NM_802_11_AP_SEC_PAIR_TKIP:
+                ciphers.append("tkip")
+            if flags & network.NM_802_11_AP_SEC_PAIR_CCMP:
+                ciphers.append("ccmp")
+        else:
+            if flags & network.NM_802_11_AP_SEC_GROUP_WEP40:
+                ciphers.append("wep40")
+            if flags & network.NM_802_11_AP_SEC_GROUP_WEP104:
+                ciphers.append("wep104")
+            if flags & network.NM_802_11_AP_SEC_GROUP_TKIP:
+                ciphers.append("tkip")
+            if flags & network.NM_802_11_AP_SEC_GROUP_CCMP:
+                ciphers.append("ccmp")
+        return ciphers
+
+    def _get_security(self):
+        if not (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \
+                (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \
+                (self._rsn_flags == network.NM_802_11_AP_SEC_NONE):
+            # No security
+            return None
+
+        if (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \
+                (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \
+                (self._rsn_flags == network.NM_802_11_AP_SEC_NONE):
+            # Static WEP, Dynamic WEP, or LEAP
+            wireless_security = WirelessSecurity()
+            wireless_security.key_mgmt = 'none'
+            return wireless_security
+
+        if (self._mode != network.NM_802_11_MODE_INFRA):
+            # Stuff after this point requires infrastructure
+            logging.error('The infrastructure mode is not supoorted'
+                          ' by your wireless device.')
+            return None
+
+        if (self._rsn_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \
+                (self._device_caps & network.NM_802_11_DEVICE_CAP_RSN):
+            # WPA2 PSK first
+            pairwise = self._add_ciphers_from_flags(self._rsn_flags, True)
+            group = self._add_ciphers_from_flags(self._rsn_flags, False)
+            wireless_security = WirelessSecurity()
+            wireless_security.key_mgmt = 'wpa-psk'
+            wireless_security.proto = 'rsn'
+            wireless_security.pairwise = pairwise
+            wireless_security.group = group
+            return wireless_security
+
+        if (self._wpa_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \
+                (self._device_caps & network.NM_802_11_DEVICE_CAP_WPA):
+            # WPA PSK
+            pairwise = self._add_ciphers_from_flags(self._wpa_flags, True)
+            group = self._add_ciphers_from_flags(self._wpa_flags, False)
+            wireless_security = WirelessSecurity()
+            wireless_security.key_mgmt = 'wpa-psk'
+            wireless_security.proto = 'wpa'
+            wireless_security.pairwise = pairwise
+            wireless_security.group = group
+            return wireless_security
 
-    def _create_palette(self):
-        p = palette.Palette(_("Mesh Network") + " " + str(self.channel),
-                            menu_after_content=True)
+    def _activate_cb(self, icon):
+        connection = network.find_connection(self._name)
+        if connection is None:
+            settings = Settings()            
+            settings.connection.id = 'Auto ' + self._name
+            settings.connection.uuid = unique_id()
+            settings.connection.type = '802-11-wireless'
+            settings.wireless.ssid = self._name
 
-        self._disconnect_item = gtk.MenuItem(_('Disconnect...'))
-        self._disconnect_item.connect('activate', self._disconnect_activate_cb)
-        p.menu.append(self._disconnect_item)
+            wireless_security = self._get_security()
+            settings.wireless_security = wireless_security
 
-        state = self._nm_device.get_state()
-        chan = wireless.freq_to_channel(self._nm_device.get_frequency())
-        if state == nmclient.DEVICE_STATE_ACTIVATED and chan == self.channel:
-            self._disconnect_item.show()
-        return p
+            connection = network.add_connection(self._name, settings)
 
-    def _disconnect_activate_cb(self, menuitem):
-        network_manager = hardwaremanager.get_network_manager()
-        if network_manager:
-            network_manager.set_active_device(self._nm_device)
+            if wireless_security is None:
+                self._connection = connection
 
-    def _activate_cb(self, icon):
-        network_manager = hardwaremanager.get_network_manager()
-        if network_manager:
-            freq = wireless.channel_to_freq(self.channel)
-            network_manager.set_active_device(self._nm_device, mesh_freq=freq)
+        obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
+        netmgr = dbus.Interface(obj, _NM_IFACE)
 
-    def _state_changed_cb(self, model):
-        self._update_state()
+        netmgr.ActivateConnection(network.SETTINGS_SERVICE, connection.path,
+                                  self._device.object_path,
+                                  self._model.object_path,
+                                  reply_handler=self.__activate_reply_cb,
+                                  error_handler=self.__activate_error_cb)
 
-    def _update_state(self):
-        state = self._nm_device.get_state()
-        chan = wireless.freq_to_channel(self._nm_device.get_frequency())
-        if state == nmclient.DEVICE_STATE_ACTIVATING and chan == self.channel:
-            self._disconnect_item.hide()
-            self.props.pulsing = True
-        elif state == nmclient.DEVICE_STATE_ACTIVATED and chan == self.channel:
-            self._disconnect_item.show()
-            self.props.pulsing = False
-        elif state == nmclient.DEVICE_STATE_INACTIVE or chan != self.channel:
-            self._disconnect_item.hide()
-            self.props.pulsing = False
+    def __activate_reply_cb(self, connection):
+        if self._connection:
+            self._connection.save()
+        logging.debug('Connection activated: %s', connection)
 
-        if self._greyed_out:
-            self.props.pulsing = False
-            self.props.base_color = XoColor('#D5D5D5,#D5D5D5')
-        else:
-            self.props.base_color = profile.get_color()
+    def __activate_error_cb(self, err):
+        logging.debug('Failed to activate connection: %s', err)
 
     def set_filter(self, query):
-        self._greyed_out = (query != '')
+        self._greyed_out = self._name.lower().find(query) == -1
         self._update_state()
+        self._update_color()
+
+    def create_keydialog(self, response):
+        keydialog.create(self._name, self._flags, self._wpa_flags,
+                         self._rsn_flags, self._device_caps, response)
+
+    def disconnect(self):
+        self._bus.remove_signal_receiver(self.__ap_properties_changed_cb,
+                                         signal_name='PropertiesChanged',
+                                         path=self._model.object_path,
+                                         dbus_interface=_NM_ACCESSPOINT_IFACE)
+
+        self._bus.remove_signal_receiver(self.__device_state_changed_cb,
+                                         signal_name='StateChanged',
+                                         path=self._device.object_path,
+                                         dbus_interface=_NM_DEVICE_IFACE)
+        self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb,
+                                         signal_name='PropertiesChanged',
+                                         path=self._device.object_path,
+                                         dbus_interface=_NM_WIRELESS_IFACE)
 
 class ActivityView(hippo.CanvasBox):
     def __init__(self, model):
@@ -364,7 +484,7 @@ class ActivityView(hippo.CanvasBox):
         self._update_palette()
 
     def _joined_changed_cb(self, widget, event):
-        logging.debug('ActivityView._joined_changed_cb: AAAA!!!!')
+        logging.debug('ActivityView._joined_changed_cb')
 
 _AUTOSEARCH_TIMEOUT = 1000
 
@@ -436,15 +556,135 @@ class MeshToolbar(gtk.Toolbar):
         self.search_entry.activate()
         return False
 
+class DeviceObserver(object):
+    def __init__(self, box, device):
+        self._box = box
+        self._bus = dbus.SystemBus()
+        self._device = device
+
+        wireless = dbus.Interface(self._device, _NM_WIRELESS_IFACE)
+        wireless.GetAccessPoints(reply_handler=self._get_access_points_reply_cb,
+                                 error_handler=self._get_access_points_error_cb)
+
+        self._bus.add_signal_receiver(self.__access_point_added_cb,
+                                      signal_name='AccessPointAdded',
+                                      path=device.object_path,
+                                      dbus_interface=_NM_WIRELESS_IFACE)
+        self._bus.add_signal_receiver(self.__access_point_removed_cb,
+                                      signal_name='AccessPointRemoved',
+                                      path=device.object_path,
+                                      dbus_interface=_NM_WIRELESS_IFACE)
+
+    def _get_access_points_reply_cb(self, access_points_o):
+        for ap_o in access_points_o:
+            ap = self._bus.get_object(_NM_SERVICE, ap_o)
+            self._box.add_access_point(self._device, ap)
+
+    def _get_access_points_error_cb(self, err):
+        logging.error('Failed to get access points: %s', err)
+
+    def __access_point_added_cb(self, access_point_o):
+        ap = self._bus.get_object(_NM_SERVICE, access_point_o)
+        self._box.add_access_point(self._device, ap)
+
+    def __access_point_removed_cb(self, access_point_o):
+        self._box.remove_access_point(access_point_o)
+
+    def disconnect(self):
+        self._bus.remove_signal_receiver(self.__access_point_added_cb,
+                                         signal_name='AccessPointAdded',
+                                         path=self._device.object_path,
+                                         dbus_interface=_NM_WIRELESS_IFACE)
+        self._bus.remove_signal_receiver(self.__access_point_removed_cb,
+                                         signal_name='AccessPointRemoved',
+                                         path=self._device.object_path,
+                                         dbus_interface=_NM_WIRELESS_IFACE)
+
+class NetworkManagerObserver(object):
+    def __init__(self, box):
+        self._box = box
+        self._bus = dbus.SystemBus()
+        self._devices = {}
+        self._netmgr = None
+
+    def listen(self):
+        try:
+            obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
+            self._netmgr = dbus.Interface(obj, _NM_IFACE)
+        except dbus.DBusException:
+            logging.debug('%s service not available', _NM_SERVICE)
+            return
+
+        self._netmgr.GetDevices(reply_handler=self.__get_devices_reply_cb,
+                                error_handler=self.__get_devices_error_cb)
+
+        self._bus.add_signal_receiver(self.__device_added_cb,
+                                      signal_name='DeviceAdded',
+                                      dbus_interface=_NM_IFACE)
+        self._bus.add_signal_receiver(self.__device_removed_cb,
+                                      signal_name='DeviceRemoved',
+                                      dbus_interface=_NM_IFACE)
+
+        settings = network.get_settings()
+        if settings is not None:
+            settings.secrets_request.connect(self.__secrets_request_cb)
+
+    def __secrets_request_cb(self, **kwargs):
+        # FIXME It would be better to do all of this async, but I cannot think
+        # of a good way to. NM could really use some love here.
+
+        netmgr_props = dbus.Interface(
+                            self._netmgr, 'org.freedesktop.DBus.Properties')
+        active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections')
+
+        for conn_o in active_connections_o:
+            obj = self._bus.get_object(_NM_IFACE, conn_o)
+            props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
+            ap_o = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject')
+
+            ap_view = self._box.access_points[ap_o]
+            ap_view.create_keydialog(kwargs['response'])
+
+    def __get_devices_reply_cb(self, devices_o):
+        for dev_o in devices_o:
+            self._check_device(dev_o)
+
+    def __get_devices_error_cb(self, err):
+        logging.error('Failed to get devices: %s', err)
+
+    def _check_device(self, device_o):
+        device = self._bus.get_object(_NM_SERVICE, device_o)
+        props = dbus.Interface(device, 'org.freedesktop.DBus.Properties')
+
+        device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
+        if device_type == network.DEVICE_TYPE_802_11_WIRELESS:
+            self._devices[device_o] = DeviceObserver(self._box, device)
+
+    def _get_device_path_error_cb(self, err):
+        logging.error('Failed to get device type: %s', err)
+
+    def __device_added_cb(self, device_o):
+        self._check_device(device_o)
+
+    def __device_removed_cb(self, device_o):
+        if device_o in self._devices:
+            observer = self._devices[device_o]
+            observer.disconnect()
+            del self._devices[device_o]
+
 class MeshBox(gtk.VBox):
     __gtype_name__ = 'SugarMeshBox'
+
     def __init__(self):
+        logging.debug("STARTUP: Loading the mesh view")
+
         gobject.GObject.__init__(self)
 
-        self._model = shellmodel.get_instance().get_mesh()
+        self.access_points = {}
+
+        self._model = neighborhood.get_model()
         self._buddies = {}
         self._activities = {}
-        self._access_points = {}
         self._mesh = {}
         self._buddy_to_activity = {}
         self._suspended = True
@@ -480,29 +720,8 @@ class MeshBox(gtk.VBox):
         self._model.connect('activity-added', self._activity_added_cb)
         self._model.connect('activity-removed', self._activity_removed_cb)
 
-        for ap_model in self._model.get_access_points():
-            self._add_access_point(ap_model)
-
-        self._model.connect('access-point-added',
-                            self._access_point_added_cb)
-        self._model.connect('access-point-removed',
-                            self._access_point_removed_cb)
-
-        if self._model.get_mesh():
-            self.__mesh_added_cb(self._model, self._model.get_mesh())
-
-        self._model.connect('mesh-added', self.__mesh_added_cb)
-        self._model.connect('mesh-removed', self.__mesh_removed_cb)
-
-    def __mesh_added_cb(self, model, meshdev):
-        self._add_mesh_icon(meshdev, 1)
-        self._add_mesh_icon(meshdev, 6)
-        self._add_mesh_icon(meshdev, 11)
-
-    def __mesh_removed_cb(self, model):
-        self._remove_mesh_icon(1)
-        self._remove_mesh_icon(6)
-        self._remove_mesh_icon(11)
+        netmgr_observer = NetworkManagerObserver(self)
+        netmgr_observer.listen()
 
     def do_size_allocate(self, allocation):
         width = allocation.width        
@@ -534,26 +753,6 @@ class MeshBox(gtk.VBox):
     def _activity_removed_cb(self, model, activity_model):
         self._remove_activity(activity_model) 
 
-    def _access_point_added_cb(self, model, ap_model):
-        self._add_access_point(ap_model)
-
-    def _access_point_removed_cb(self, model, ap_model):
-        self._remove_access_point(ap_model) 
-
-    def _add_mesh_icon(self, meshdev, channel):
-        if self._mesh.has_key(channel):
-            self._remove_mesh_icon(channel)
-        if not meshdev:
-            return
-        self._mesh[channel] = MeshDeviceView(meshdev, channel)
-        self._layout.add(self._mesh[channel])
-
-    def _remove_mesh_icon(self, channel):
-        if not self._mesh.has_key(channel):
-            return
-        self._layout.remove(self._mesh[channel])
-        del self._mesh[channel]
-
     def _add_alone_buddy(self, buddy_model):
         icon = BuddyIcon(buddy_model)
         if buddy_model.is_owner():
@@ -563,22 +762,22 @@ class MeshBox(gtk.VBox):
         if hasattr(icon, 'set_filter'):
             icon.set_filter(self._query)
 
-        self._buddies[buddy_model.get_key()] = icon
+        self._buddies[buddy_model.get_buddy().object_path()] = icon
 
     def _remove_alone_buddy(self, buddy_model):
-        icon = self._buddies[buddy_model.get_key()]
+        icon = self._buddies[buddy_model.get_buddy().object_path()]
         self._layout.remove(icon)
-        del self._buddies[buddy_model.get_key()]
+        del self._buddies[buddy_model.get_buddy().object_path()]
         icon.destroy()
 
     def _remove_buddy(self, buddy_model):
-        key = buddy_model.get_key()
-        if self._buddies.has_key(key):
+        object_path = buddy_model.get_buddy().object_path()
+        if self._buddies.has_key(object_path):
             self._remove_alone_buddy(buddy_model)
         else:
             for activity in self._activities.values():
-                if activity.has_buddy_icon(key):
-                    activity.remove_buddy_icon(key)
+                if activity.has_buddy_icon(object_path):
+                    activity.remove_buddy_icon(object_path)
 
     def _move_buddy(self, buddy_model, activity_model):
         self._remove_buddy(buddy_model)
@@ -589,7 +788,7 @@ class MeshBox(gtk.VBox):
             activity = self._activities[activity_model.get_id()]
 
             icon = BuddyIcon(buddy_model, style.STANDARD_ICON_SIZE)
-            activity.add_buddy_icon(buddy_model.get_key(), icon)
+            activity.add_buddy_icon(buddy_model.get_buddy().object_path(), icon)
 
             if hasattr(icon, 'set_filter'):
                 icon.set_filter(self._query)
@@ -609,31 +808,34 @@ class MeshBox(gtk.VBox):
         del self._activities[activity_model.get_id()]
         icon.destroy()
 
-    def _add_access_point(self, ap_model):
-        meshdev = self._model.get_mesh()
-        icon = AccessPointView(ap_model, meshdev)
+    def add_access_point(self, device, ap):
+        icon = AccessPointView(device, ap)
         self._layout.add(icon)
 
         if hasattr(icon, 'set_filter'):
             icon.set_filter(self._query)
 
-        self._access_points[ap_model.get_id()] = icon
+        self.access_points[ap.object_path] = icon
 
-    def _remove_access_point(self, ap_model):
-        icon = self._access_points[ap_model.get_id()]
-        self._layout.remove(icon)
-        del self._access_points[ap_model.get_id()]
+    def remove_access_point(self, ap_o):
+        if ap_o in self.access_points:
+            icon = self.access_points[ap_o]
+            icon.disconnect()
+            self._layout.remove(icon)
+            del self.access_points[ap_o]
+        else:
+            logging.error('Can not remove access point %s' % ap_o)
 
     def suspend(self):
         if not self._suspended:
             self._suspended = True
-            for ap in self._access_points.values():
+            for ap in self.access_points.values():
                 ap.props.paused = True
 
     def resume(self):
         if self._suspended:
             self._suspended = False
-            for ap in self._access_points.values():
+            for ap in self.access_points.values():
                 ap.props.paused = False
 
     def _toolbar_query_changed_cb(self, toolbar, query):
diff --git a/src/view/home/keydialog.py b/src/view/home/keydialog.py
new file mode 100644
index 0000000..92e8f40
--- /dev/null
+++ b/src/view/home/keydialog.py
@@ -0,0 +1,311 @@
+# Copyright (C) 2006-2007 Red Hat, Inc.
+#
+# 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+
+import md5
+from gettext import gettext as _
+
+import gtk
+import dbus
+
+from model import network
+from model.network import Secrets
+
+IW_AUTH_ALG_OPEN_SYSTEM = 'open'
+IW_AUTH_ALG_SHARED_KEY  = 'shared'
+
+def string_is_hex(key):
+    is_hex = True
+    for c in key:
+        if not 'a' <= c.lower() <= 'f' and not '0' <= c <= '9':
+            is_hex = False
+    return is_hex
+
+def string_is_ascii(string):
+    try:
+        string.encode('ascii')
+        return True
+    except UnicodeEncodeError:
+        return False
+
+def string_to_hex(passphrase):
+    key = ''
+    for c in passphrase:
+        key += '%02x' % ord(c)
+    return key
+
+def hash_passphrase(passphrase):
+    # passphrase must have a length of 64
+    if len(passphrase) > 64:
+        passphrase = passphrase[:64]
+    elif len(passphrase) < 64:
+        while len(passphrase) < 64:
+            passphrase += passphrase[:64 - len(passphrase)]
+    passphrase = md5.new(passphrase).digest()
+    return string_to_hex(passphrase)[:26]
+
+class CanceledKeyRequestError(dbus.DBusException):
+    def __init__(self):
+        dbus.DBusException.__init__(self)
+        self._dbus_error_name = network.NM_SETTINGS_IFACE + '.CanceledError'
+
+class KeyDialog(gtk.Dialog):
+    def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response):
+        gtk.Dialog.__init__(self, flags=gtk.DIALOG_MODAL)
+        self.set_title("Wireless Key Required")
+
+        self._response = response
+        self._entry = None
+        self._ssid = ssid
+        self._flags = flags
+        self._wpa_flags = wpa_flags
+        self._rsn_flags = rsn_flags
+        self._dev_caps = dev_caps
+
+        self.set_has_separator(False)        
+
+        label = gtk.Label("A wireless encryption key is required for\n" \
+                          " the wireless network '%s'." % self._ssid)
+        self.vbox.pack_start(label)
+
+        self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+                         gtk.STOCK_OK, gtk.RESPONSE_OK)
+        self.set_default_response(gtk.RESPONSE_OK)
+        self.set_has_separator(True)
+
+    def add_key_entry(self):
+        self._entry = gtk.Entry()
+        self._entry.connect('changed', self._update_response_sensitivity)
+        self._entry.connect('activate', self._entry_activate_cb)
+        self.vbox.pack_start(self._entry)
+        self.vbox.set_spacing(6)
+        self.vbox.show_all()
+
+        self._update_response_sensitivity()
+        self._entry.grab_focus()
+
+    def _entry_activate_cb(self, entry):
+        self.response(gtk.RESPONSE_OK)
+
+    def create_security(self):
+        raise NotImplementedError
+
+    def get_response_object(self):
+        return self._response
+
+WEP_PASSPHRASE = 1
+WEP_HEX = 2
+WEP_ASCII = 3
+
+class WEPKeyDialog(KeyDialog):
+    def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response):
+        KeyDialog.__init__(self, ssid, flags, wpa_flags, rsn_flags,
+                           dev_caps, response)
+
+        # WEP key type
+        self.key_store = gtk.ListStore(str, int)
+        self.key_store.append(["Passphrase (128-bit)", WEP_PASSPHRASE])
+        self.key_store.append(["Hex (40/128-bit)", WEP_HEX])
+        self.key_store.append(["ASCII (40/128-bit)", WEP_ASCII])
+
+        self.key_combo = gtk.ComboBox(self.key_store)
+        cell = gtk.CellRendererText()
+        self.key_combo.pack_start(cell, True)
+        self.key_combo.add_attribute(cell, 'text', 0)
+        self.key_combo.set_active(0)
+        self.key_combo.connect('changed', self._key_combo_changed_cb)
+
+        hbox = gtk.HBox()
+        hbox.pack_start(gtk.Label(_("Key Type:")))
+        hbox.pack_start(self.key_combo)
+        hbox.show_all()
+        self.vbox.pack_start(hbox)
+
+        # Key entry field
+        self.add_key_entry()
+
+        # WEP authentication mode
+        self.auth_store = gtk.ListStore(str, str)
+        self.auth_store.append(["Open System", IW_AUTH_ALG_OPEN_SYSTEM])
+        self.auth_store.append(["Shared Key", IW_AUTH_ALG_SHARED_KEY])
+
+        self.auth_combo = gtk.ComboBox(self.auth_store)
+        cell = gtk.CellRendererText()
+        self.auth_combo.pack_start(cell, True)
+        self.auth_combo.add_attribute(cell, 'text', 0)
+        self.auth_combo.set_active(0)
+
+        hbox = gtk.HBox()
+        hbox.pack_start(gtk.Label(_("Authentication Type:")))
+        hbox.pack_start(self.auth_combo)
+        hbox.show_all()
+
+        self.vbox.pack_start(hbox)
+
+    def _key_combo_changed_cb(self, widget):
+        self._update_response_sensitivity()
+
+    def _get_security(self):
+        key = self._entry.get_text()
+
+        it = self.key_combo.get_active_iter()
+        (key_type, ) = self.key_store.get(it, 1)
+
+        if key_type == WEP_PASSPHRASE:
+            key = hash_passphrase(key)
+        elif key_type == WEP_ASCII:
+            key = string_to_hex(key)
+
+        it = self.auth_combo.get_active_iter()
+        (auth_alg, ) = self.auth_store.get(it, 1)
+
+        return (key, auth_alg)
+
+    def print_security(self):
+        (key, auth_alg) = self._get_security()
+        print "Key: %s" % key
+        print "Auth: %d" % auth_alg
+
+    def create_security(self):
+        (key, auth_alg) = self._get_security()
+        secrets = Secrets()
+        secrets.wep_key = key
+        secrets.auth_alg = auth_alg
+        return secrets
+
+    def _update_response_sensitivity(self, ignored=None):
+        key = self._entry.get_text()
+        it = self.key_combo.get_active_iter()
+        (key_type, ) = self.key_store.get(it, 1)
+
+        valid = False
+        if key_type == WEP_PASSPHRASE:
+            # As the md5 passphrase can be of any length and has no indicator,
+            # we cannot check for the validity of the input.
+            if len(key) > 0:
+                valid = True
+        elif key_type == WEP_ASCII:
+            if len(key) == 5 or len(key) == 13:
+                valid = string_is_ascii(key)
+        elif key_type == WEP_HEX:
+            if len(key) == 10 or len(key) == 26:
+                valid = string_is_hex(key)
+
+        self.set_response_sensitive(gtk.RESPONSE_OK, valid)
+
+class WPAKeyDialog(KeyDialog):
+    def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response):
+        KeyDialog.__init__(self, ssid, flags, wpa_flags, rsn_flags,
+                           dev_caps, response)
+        self.add_key_entry()
+
+        self.store = gtk.ListStore(str)
+        self.store.append([_("WPA & WPA2 Personal")])
+
+        self.combo = gtk.ComboBox(self.store)
+        cell = gtk.CellRendererText()
+        self.combo.pack_start(cell, True)
+        self.combo.add_attribute(cell, 'text', 0)
+        self.combo.set_active(0)
+
+        self.hbox = gtk.HBox()
+        self.hbox.pack_start(gtk.Label(_("Wireless Security:")))
+        self.hbox.pack_start(self.combo)
+        self.hbox.show_all()
+
+        self.vbox.pack_start(self.hbox)
+
+    def _get_security(self):
+        ssid = self._ssid
+        key = self._entry.get_text()
+        is_hex = string_is_hex(key)
+
+        real_key = None
+        if len(key) == 64 and is_hex:
+            # Hex key
+            real_key = key
+        elif len(key) >= 8 and len(key) <= 63:
+            # passphrase
+            from subprocess import Popen, PIPE
+            p = Popen(['/usr/sbin/wpa_passphrase', ssid, key], stdout=PIPE)
+            for line in p.stdout:
+                if line.strip().startswith("psk="):
+                    real_key = line.strip()[4:]
+            if p.wait() != 0:
+                raise RuntimeError("Error hashing passphrase")
+            if real_key and len(real_key) != 64:
+                real_key = None
+
+        if not real_key:
+            raise RuntimeError("Invalid key")
+
+        return real_key
+
+    def print_security(self):
+        key = self._get_security()
+        print "Key: %s" % key
+
+    def create_security(self):
+        secrets = Secrets()
+        secrets.psk = self._get_security()
+        return secrets
+
+    def _update_response_sensitivity(self, ignored=None):
+        key = self._entry.get_text()
+        is_hex = string_is_hex(key)
+
+        valid = False
+        if len(key) == 64 and is_hex:
+            # hex key
+            valid = True
+        elif len(key) >= 8 and len(key) <= 63:
+            # passphrase
+            valid = True
+        self.set_response_sensitive(gtk.RESPONSE_OK, valid)
+        return False
+
+def create(ssid, flags, wpa_flags, rsn_flags, dev_caps, response):
+    if wpa_flags == network.NM_802_11_AP_SEC_NONE and \
+            rsn_flags == network.NM_802_11_AP_SEC_NONE:
+        key_dialog = WEPKeyDialog(ssid, flags, wpa_flags, rsn_flags,
+                                  dev_caps, response)
+    else:
+        key_dialog = WPAKeyDialog(ssid, flags, wpa_flags, rsn_flags,
+                                  dev_caps, response)
+
+    key_dialog.connect("response", _key_dialog_response_cb)
+    key_dialog.connect("destroy", _key_dialog_destroy_cb)
+    key_dialog.show_all()
+
+def _key_dialog_destroy_cb(key_dialog, data=None):
+    _key_dialog_response_cb(key_dialog, gtk.RESPONSE_CANCEL)
+
+def _key_dialog_response_cb(key_dialog, response_id):
+    response = key_dialog.get_response_object()
+    secrets = None
+    if response_id == gtk.RESPONSE_OK:
+        secrets = key_dialog.create_security()
+
+    if response_id in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_NONE]:
+        # key dialog dialog was canceled; send the error back to NM
+        response.set_error(CanceledKeyRequestError())
+    elif response_id == gtk.RESPONSE_OK:
+        if not secrets:
+            raise RuntimeError("Invalid security arguments.")
+        response.set_secrets(secrets)
+    else:
+        raise RuntimeError("Unhandled key dialog response %d" % response_id)
+
+    key_dialog.destroy()