[Sugar-devel] [PATCH] fix network disconnect and discard history

James Cameron quozl at laptop.org
Tue May 25 03:41:10 EDT 2010


User interface changes:

- enable the disconnect button on the access point menu in the
  neighbourhood view, (rather than the button doing nothing),

- fix the disconnect button on the wireless device icon in the frame
  so that the disconnection remains effective, (rather than
  disconnecting and then reconnecting automatically),

- enable the discard network history button in the network control
  panel, which also now forces a disconnect, and will be insensitive
  if there are no networks to be discarded, (rather than the button
  doing nothing),

- enforce consistency between the neighbourhood view, the frame, and
  the control panel, with respect to how the access point is shown.

References:

    http://dev.laptop.org/ticket/9977 (fixes a workaround)
    http://bugs.sugarlabs.org/ticket/1673
    http://bugs.sugarlabs.org/ticket/1802
    http://bugs.sugarlabs.org/ticket/1737
    http://bugs.sugarlabs.org/ticket/1736
    http://bugs.sugarlabs.org/ticket/1608
    http://dev.laptop.org/ticket/9788
---
 extensions/cpsection/network/model.py |   12 ++++--
 extensions/cpsection/network/view.py  |    8 ++++-
 extensions/deviceicon/network.py      |   37 ++++++++++---------
 src/jarabe/desktop/meshbox.py         |   61 +++++++++++++++++++++----------
 src/jarabe/model/network.py           |   62 ++++++++++++++++++++++++++------
 5 files changed, 125 insertions(+), 55 deletions(-)

diff --git a/extensions/cpsection/network/model.py b/extensions/cpsection/network/model.py
index e1c3dab..2bc5e3a 100644
--- a/extensions/cpsection/network/model.py
+++ b/extensions/cpsection/network/model.py
@@ -17,6 +17,7 @@
 
 import dbus
 from gettext import gettext as _
+from jarabe.model import network
 import gconf
 
 _NM_SERVICE = 'org.freedesktop.NetworkManager'
@@ -68,7 +69,7 @@ def get_radio():
     try:
         bus = dbus.SystemBus()
         obj = bus.get_object(_NM_SERVICE, _NM_PATH)
-        nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
+        nm_props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
     except dbus.DBusException:
         raise ReadError('%s service not available' % _NM_SERVICE)
 
@@ -89,7 +90,7 @@ def set_radio(state):
         try:
             bus = dbus.SystemBus()
             obj = bus.get_object(_NM_SERVICE, _NM_PATH)
-            nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
+            nm_props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
         except dbus.DBusException:
             raise ReadError('%s service not available' % _NM_SERVICE)
         nm_props.Set(_NM_IFACE, 'WirelessEnabled', True)
@@ -97,7 +98,7 @@ def set_radio(state):
         try:
             bus = dbus.SystemBus()
             obj = bus.get_object(_NM_SERVICE, _NM_PATH)
-            nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
+            nm_props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
         except dbus.DBusException:
             raise ReadError('%s service not available' % _NM_SERVICE)
         nm_props.Set(_NM_IFACE, 'WirelessEnabled', False)
@@ -116,7 +117,10 @@ def clear_registration():
 def clear_networks():
     """Clear saved passwords and network configurations.
     """
-    pass
+    network.clear_wifi_connections()
+
+def count_networks():
+    return network.count_wifi_connections()
 
 def get_publish_information():
     client = gconf.client_get_default()
diff --git a/extensions/cpsection/network/view.py b/extensions/cpsection/network/view.py
index 588daeb..b0f1336 100644
--- a/extensions/cpsection/network/view.py
+++ b/extensions/cpsection/network/view.py
@@ -104,6 +104,8 @@ class Network(SectionView):
         self._clear_history_button = gtk.Button()
         self._clear_history_button.set_label(_('Discard network history'))
         box_clear_history.pack_start(self._clear_history_button, expand=False)
+        if self._model.count_networks() == 0:
+            self._clear_history_button.set_sensitive(False)
         self._clear_history_button.show()
         box_wireless.pack_start(box_clear_history, expand=False)
         box_clear_history.show()
@@ -217,7 +219,9 @@ class Network(SectionView):
             self._radio_alert.props.msg = detail
             self._radio_valid = False
         else:
-            self._radio_valid = True            
+            self._radio_valid = True
+            if self._model.count_networks() != 0:
+                self._clear_history_button.set_sensitive(True)
 
         self._validate()
         return False
@@ -248,3 +252,5 @@ class Network(SectionView):
 
     def __network_configuration_reset_cb(self, widget):
         self._model.clear_networks()
+        if self._model.count_networks() == 0:
+            self._clear_history_button.set_sensitive(False)
diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
index 94a4293..a828497 100644
--- a/extensions/deviceicon/network.py
+++ b/extensions/deviceicon/network.py
@@ -352,8 +352,7 @@ class WirelessDeviceView(ToolButton):
         self.set_palette(self._palette)
         self._palette.set_group_id('frame')
 
-        self._device_props = dbus.Interface(self._device, 
-                                            'org.freedesktop.DBus.Properties')
+        self._device_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE)
         self._device_props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, 
                               reply_handler=self.__get_device_props_reply_cb,
                               error_handler=self.__get_device_props_error_cb)
@@ -394,7 +393,7 @@ class WirelessDeviceView(ToolButton):
                 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 = dbus.Interface(active_ap, dbus.PROPERTIES_IFACE)
 
             props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True,
                          reply_handler=self.__get_all_ap_props_reply_cb,
@@ -508,17 +507,21 @@ class WirelessDeviceView(ToolButton):
         self._icon.props.base_color = self._color
 
     def __deactivate_connection_cb(self, palette, data=None):
+        connection = network.find_connection_by_ssid(self._name)
+        if connection:
+            if self._mode == network.NM_802_11_MODE_INFRA:
+                connection.set_disconnected()
+
         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')
+            netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE)
             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')
+                props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
                 ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject')
                 if ap_op == self._active_ap_op:
                     netmgr.DeactivateConnection(conn_o)
@@ -608,8 +611,7 @@ class OlpcMeshDeviceView(ToolButton):
         self.set_palette(self._palette)
         self._palette.set_group_id('frame')
 
-        self._device_props = dbus.Interface(self._device,
-                                            'org.freedesktop.DBus.Properties')
+        self._device_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE)
         self._device_props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True,
                               reply_handler=self.__get_device_props_reply_cb,
                               error_handler=self.__get_device_props_error_cb)
@@ -681,19 +683,19 @@ class OlpcMeshDeviceView(ToolButton):
     def __deactivate_connection(self, palette, data=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')
+        netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE)
         active_connections_o = netmgr_props.Get(_NM_IFACE,
                                                 'ActiveConnections')
 
         for conn_o in active_connections_o:
             # The connection path for a mesh connection is the device itself.
             obj = self._bus.get_object(_NM_IFACE, conn_o)
-            props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
+            props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
             ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject')
 
             try:
                 obj = self._bus.get_object(_NM_IFACE, ap_op)
-                props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
+                props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
                 type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
                 if type == network.DEVICE_TYPE_802_11_OLPC_MESH:
                     netmgr.DeactivateConnection(conn_o)
@@ -756,7 +758,7 @@ class GsmDeviceView(TrayIcon):
 
         self._palette = palette
 
-        props = dbus.Interface(self._device, 'org.freedesktop.DBus.Properties')
+        props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE)
         props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True,
                      reply_handler=self.__current_state_check_cb,
                      error_handler=self.__current_state_check_error_cb)
@@ -785,12 +787,12 @@ class GsmDeviceView(TrayIcon):
     def __gsm_disconnect_cb(self, palette, data=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')
+        netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE)
         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')
+            props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
             devices = props.Get(_NM_ACTIVE_CONN_IFACE, 'Devices')
             if self._device.object_path in devices:
                 netmgr.DeactivateConnection(
@@ -910,7 +912,7 @@ class WiredDeviceObserver(object):
         self._device_view = None
         self._tray = tray
 
-        props = dbus.Interface(self._device, 'org.freedesktop.DBus.Properties')
+        props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE)
         props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True,
                      reply_handler=self.__get_device_props_reply_cb,
                      error_handler=self.__get_device_props_error_cb)
@@ -938,8 +940,7 @@ class WiredDeviceObserver(object):
 
     def _update_state(self, state):
         if state == network.DEVICE_STATE_ACTIVATED:
-            props = dbus.Interface(self._device,
-                                   'org.freedesktop.DBus.Properties')
+            props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE)
             address = props.Get(_NM_DEVICE_IFACE, 'Ip4Address')
             speed = props.Get(_NM_WIRED_IFACE, 'Speed')
             self._device_view = WiredDeviceView(speed, address)
@@ -997,7 +998,7 @@ class NetworkManagerObserver(object):
 
     def _check_device(self, device_op):
         nm_device = self._bus.get_object(_NM_SERVICE, device_op)
-        props = dbus.Interface(nm_device, 'org.freedesktop.DBus.Properties')
+        props = dbus.Interface(nm_device, dbus.PROPERTIES_IFACE)
 
         device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
         if device_type == network.DEVICE_TYPE_802_3_ETHERNET:
diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py
index a04922b..280adb9 100644
--- a/src/jarabe/desktop/meshbox.py
+++ b/src/jarabe/desktop/meshbox.py
@@ -86,7 +86,6 @@ class WirelessNetworkView(CanvasPulsingIcon):
         self._rsn_flags = initial_ap.rsn_flags
         self._device_caps = 0
         self._device_state = None
-        self._connection = None
         self._color = None
 
         if self._mode == network.NM_802_11_MODE_ADHOC \
@@ -115,18 +114,9 @@ class WirelessNetworkView(CanvasPulsingIcon):
         self.set_palette(self._palette)
         self._palette_icon.props.xo_color = self._color
 
-        if network.find_connection_by_ssid(self._name) is not None:
-            self.props.badge_name = "emblem-favorite"
-            self._palette_icon.props.badge_name = "emblem-favorite"
-        elif initial_ap.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._update_badge()
 
-        interface_props = dbus.Interface(self._device,
-                                         'org.freedesktop.DBus.Properties')
+        interface_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE)
         interface_props.Get(_NM_DEVICE_IFACE, 'State',
                             reply_handler=self.__get_device_state_reply_cb,
                             error_handler=self.__get_device_state_error_cb)
@@ -174,6 +164,7 @@ class WirelessNetworkView(CanvasPulsingIcon):
     def __device_state_changed_cb(self, new_state, old_state, reason):
         self._device_state = new_state
         self._update_state()
+        self._update_badge()
 
     def __update_active_ap(self, ap_path):
         if ap_path in self._access_points:
@@ -214,6 +205,7 @@ class WirelessNetworkView(CanvasPulsingIcon):
     def _update(self):
         self._update_state()
         self._update_color()
+        self._update_badge()
 
     def _update_state(self):
         if self._active_ap is not None:
@@ -266,8 +258,40 @@ class WirelessNetworkView(CanvasPulsingIcon):
         else:
             self.props.base_color = self._color
 
+    def _update_badge(self):
+        if network.find_connection_by_ssid(self._name) is not None:
+            self.props.badge_name = "emblem-favorite"
+            self._palette_icon.props.badge_name = "emblem-favorite"
+        elif 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
+
     def _disconnect_activate_cb(self, item):
-        pass
+        connection = network.find_connection_by_ssid(self._name)
+        if connection:
+            if self._mode == network.NM_802_11_MODE_INFRA:
+                connection.set_disconnected()
+
+        obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
+        netmgr = dbus.Interface(obj, _NM_IFACE)
+
+        netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE)
+        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, dbus.PROPERTIES_IFACE)
+            state = props.Get(_NM_ACTIVE_CONN_IFACE, 'State')
+            if state == network.NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
+                ap_o = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject')
+                if ap_o != '/' and self.find_ap(ap_o) is not None:
+                    netmgr.DeactivateConnection(conn_o)
+                else:
+                    logging.error('Could not determine AP for'
+                                  ' specific object %s' % conn_o)
 
     def _add_ciphers_from_flags(self, flags, pairwise):
         ciphers = []
@@ -456,14 +480,12 @@ class OlpcMeshView(CanvasPulsingIcon):
         self._greyed_out = False
         self._name = ''
         self._device_state = None
-        self._connection = None
         self._active = False
         device = mesh_mgr.mesh_device
 
         self.connect('button-release-event', self.__button_release_event_cb)
 
-        interface_props = dbus.Interface(device,
-                                         'org.freedesktop.DBus.Properties')
+        interface_props = dbus.Interface(device, dbus.PROPERTIES_IFACE)
         interface_props.Get(_NM_DEVICE_IFACE, 'State',
                             reply_handler=self.__get_device_state_reply_cb,
                             error_handler=self.__get_device_state_error_cb)
@@ -849,13 +871,12 @@ class NetworkManagerObserver(object):
         # 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')
+        netmgr_props = dbus.Interface(self._netmgr, dbus.PROPERTIES_IFACE)
         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')
+            props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
             state = props.Get(_NM_ACTIVE_CONN_IFACE, 'State')
             if state == network.NM_ACTIVE_CONNECTION_STATE_ACTIVATING:
                 ap_o = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject')
@@ -879,7 +900,7 @@ class NetworkManagerObserver(object):
 
     def _check_device(self, device_o):
         device = self._bus.get_object(_NM_SERVICE, device_o)
-        props = dbus.Interface(device, 'org.freedesktop.DBus.Properties')
+        props = dbus.Interface(device, dbus.PROPERTIES_IFACE)
 
         device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
         if device_type == network.DEVICE_TYPE_802_11_WIRELESS:
diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py
index 3a949da..33088c4 100644
--- a/src/jarabe/model/network.py
+++ b/src/jarabe/model/network.py
@@ -330,6 +330,13 @@ class NMSettings(dbus.service.Object):
         self.secrets_request.send(self, connection=sender,
                                   response=kwargs['response'])
 
+    def clear_wifi_connections(self):
+        for uuid in self.connections.keys():
+            conn = self.connections[uuid]
+            if conn.type == NM_CONNECTION_TYPE_802_11_WIRELESS:
+                conn.Removed()
+                self.connections.pop(uuid)
+
 class SecretsResponse(object):
     ''' Intermediate object to report the secrets from the dialog
     back to the connection object and which will inform NM
@@ -358,6 +365,16 @@ class NMSettingsConnection(dbus.service.Object):
         self._settings = settings
         self._secrets = secrets
 
+    @dbus.service.signal(dbus_interface=NM_CONNECTION_IFACE,
+                         signature='')
+    def Removed(self):
+        pass
+
+    @dbus.service.signal(dbus_interface=NM_CONNECTION_IFACE,
+                         signature='a{sa{sv}}')
+    def Updated(self, settings):
+        pass
+
     def set_connected(self):
         if self._settings.connection.type == NM_CONNECTION_TYPE_GSM:
             self._settings.connection.timestamp = int(time.time())
@@ -366,8 +383,17 @@ class NMSettingsConnection(dbus.service.Object):
                 self._settings.connection.autoconnect = True
                 self._settings.connection.timestamp = int(time.time())
                 if self._settings.connection.type == NM_CONNECTION_TYPE_802_11_WIRELESS:
+                    self.Updated(self._settings.get_dict())
                     self.save()
 
+    def set_disconnected(self):
+        if self._settings.connection.type != NM_CONNECTION_TYPE_GSM and \
+               self._settings.connection.autoconnect:
+            self._settings.connection.autoconnect = False
+            self._settings.connection.timestamp = None
+            self.Updated(self._settings.get_dict())
+            self.save()
+
     def set_secrets(self, secrets):
         self._secrets = secrets
         if self._settings.connection.type == NM_CONNECTION_TYPE_802_11_WIRELESS:
@@ -377,8 +403,7 @@ class NMSettingsConnection(dbus.service.Object):
         return self._settings
 
     def save(self):
-        profile_path = env.get_profile_path()
-        config_path = os.path.join(profile_path, 'nm', 'connections.cfg')
+        config_path = _get_wifi_connections_path()
 
         config = ConfigParser.ConfigParser()
         try:
@@ -477,8 +502,7 @@ class AccessPoint(gobject.GObject):
         self.mode = 0
 
     def initialize(self):
-        model_props = dbus.Interface(self.model,
-            'org.freedesktop.DBus.Properties')
+        model_props = dbus.Interface(self.model, dbus.PROPERTIES_IFACE)
         model_props.GetAll(NM_ACCESSPOINT_IFACE, byte_arrays=True,
                            reply_handler=self._ap_properties_changed_cb,
                            error_handler=self._get_all_props_error_cb)
@@ -590,19 +614,23 @@ def add_connection(uuid, settings, secrets=None):
     _nm_settings.add_connection(uuid, conn)
     return conn
 
-def load_wifi_connections():
+def _get_wifi_connections_path():
     profile_path = env.get_profile_path()
-    config_path = os.path.join(profile_path, 'nm', 'connections.cfg')
+    return os.path.join(profile_path, 'nm', 'connections.cfg')
 
-    config = ConfigParser.ConfigParser()
+def _create_wifi_connections(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')
+    f.close()
+
+def load_wifi_connections():
+    config_path = _get_wifi_connections_path()
 
     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()
+        _create_wifi_connections(config_path)
 
+    config = ConfigParser.ConfigParser()
     try:
         if not config.read(config_path):
             logging.error('Error reading the nm config file')
@@ -708,3 +736,13 @@ def find_gsm_connection():
 
     logging.debug('There is no gsm connection in the NMSettings.')
     return None
+
+def count_wifi_connections():
+    return len(get_settings().connections)
+
+def clear_wifi_connections():
+    if _nm_settings is not None:
+        _nm_settings.clear_wifi_connections()
+
+    config_path = _get_wifi_connections_path()
+    _create_wifi_connections(config_path)
-- 
1.7.1



More information about the Sugar-devel mailing list