rewrote settings and daemon - Bug #11109
authorFredrik Wendt <fredrik@wendt.se>
Mon, 23 Aug 2010 21:44:08 +0000 (22:44 +0100)
committerFredrik Wendt <fredrik@wendt.se>
Mon, 23 Aug 2010 21:44:08 +0000 (22:44 +0100)
package/src/wifi_assistant/daemon.py
package/src/wifi_assistant/launcher.py
package/src/wifi_assistant/settings/ApplicationSettings.py [new file with mode: 0644]
package/src/wifi_assistant/settings/NetworkSetting.py [new file with mode: 0644]
package/src/wifi_assistant/settings/NetworkSettings.py [new file with mode: 0644]
package/test/unit/settings/__init__.py [new file with mode: 0644]
package/test/unit/settings/test_ApplicationSettings.py [new file with mode: 0644]
package/test/unit/settings/test_NetworkSettings.py [new file with mode: 0644]
package/test/unit/test_Daemon.py [new file with mode: 0644]

index ab60b34..d8d3215 100644 (file)
@@ -4,29 +4,75 @@ import conic
 import gobject
 
 from launcher import Launcher
 import gobject
 
 from launcher import Launcher
-from settings import Settings
 
 def _(str):
     return str
 
 class Daemon():
     
 
 def _(str):
     return str
 
 class Daemon():
     
-    def __init__(self, launcher, settings, parent_window):
-        self._settings = settings
+    def __init__(self, launcher, application_settings, network_settings, parent_window):
+        self._application_settings = application_settings
+        self._network_settings = network_settings
         self._parent = parent_window
         self._launcher = launcher
         self._parent = parent_window
         self._launcher = launcher
-        self._popup = self._settings.getUsePopup()
+        self._popup = self._application_settings.getUsePopup()
 
 
 
 
-    def launch_browser(self):
-        url = self._settings.getUrlToOpen()
-        self._launcher.openUrl(url)
+    def connectionEstablished(self, ssid):
+        settings = self._network_settings.get(ssid)
+        if settings is None:
+            if self.showDecisionDialog(ssid):
+                defaults = self._network_settings.getDefaultSettings()
+                self.launchBrowser(defaults)
+            return
+    
+        if settings.getLaunchingOfBrowserEnabled():
+            self.launchBrowser(settings)
     
     
+
+    def launchBrowser(self, settings):
+        browser_name = settings.getNameOfBrowserToLaunch()
+        browser_options = settings.getBrowserOptions()
+        if 'url' in browser_options:
+            self._launcher.launchBrowser(browser_name, browser_options)
+        # the following line is the backwards compatible line
+        else:
+            settings = self._network_settings.getDefaultSettings()
+            self.launchBrowser(settings)
     
     
-    def show_decision_dialog(self, ssid):
+    def showDecisionDialog(self, ssid):
         if not self._popup:
         if not self._popup:
-            return
+            return False
+        
+        dialog = self._createDialog(ssid)
+        
+        dialog.show_all()
+        result = dialog.run()
+        dialog.hide()
+        
+        launch_browser = (result == gtk.RESPONSE_YES)
+        if checkbox.get_active():
+            setting = NetworkSetting()
+            setting.setNetworkName(ssid)
+            setting.setLaunchingOfBrowserEnabled(launch_browser)
+            self._network_settings.save(setting)
         
         
+        return launch_browser
+    
+    def start(self):
+        self._connection = conic.Connection()
+        self._connection.connect("connection-event", self._connectionEventCallback)
+        self._connection.set_property("automatic-connection-events", True)
+        self._application_settings.addUsePopupListener(self._usePopupEventCallback)
+        gtk.main()
+     
+    
+    def stop(self):
+        self._application_settings.removeUsePopupListener(self._usePopupEventCallback)
+        self._connection.set_property("automatic-connection-events", False)
+        
+    
+    def _createDialog(self, ssid):
         dialog = gtk.Dialog(ssid, self._parent)
         dialog.vbox.set_homogeneous(False)
         
         dialog = gtk.Dialog(ssid, self._parent)
         dialog.vbox.set_homogeneous(False)
         
@@ -44,29 +90,10 @@ class Daemon():
         checkbox.set_active(True)
         dialog.vbox.add(checkbox)
         
         checkbox.set_active(True)
         dialog.vbox.add(checkbox)
         
-        dialog.show_all()
-        result = dialog.run()
-        dialog.hide()
-        
-        launchBrowser = (result == gtk.RESPONSE_YES)
-        if checkbox.get_active():
-            self._settings.setLaunchSetting(ssid, launchBrowser)
-        
-        return launchBrowser
+        return dialog
     
     
-    
-    def connection_established(self, ssid):
-        value = self._settings.getLaunchSetting(ssid)
-        if value is None:
-            if self.show_decision_dialog(ssid):
-                self.launch_browser()
-            return
-    
-        if value:
-            self.launch_browser()
-    
-
-    def _connection_cb(self, connection, event):
+        
+    def _connectionEventCallback(self, connection, event):
         status = event.get_status()
         if status == conic.STATUS_CONNECTED:
             # assemble id > name dict
         status = event.get_status()
         if status == conic.STATUS_CONNECTED:
             # assemble id > name dict
@@ -82,28 +109,15 @@ class Daemon():
             iap_name = None
             if (iap_id_to_name.has_key(iap_id)):
                 iap_name = iap_id_to_name[iap_id]
             iap_name = None
             if (iap_id_to_name.has_key(iap_id)):
                 iap_name = iap_id_to_name[iap_id]
-            self.connection_established(iap_name)
+            self.connectionEstablished(iap_name)
     
 
     
 
-    def start(self):
-        self._connection = conic.Connection()
-        self._connection.connect("connection-event", self._connection_cb)
-        self._connection.set_property("automatic-connection-events", True)
-        self._settings.addUsePopupListener(self._activateCallback)
-        gtk.main()
-     
-    
-    def stop(self):
-        self._settings.removeUsePopupListener(self._activateCallback)
-        self._connection.set_property("automatic-connection-events", False)
-        
-    
-    def _activateCallback(self, gconfClient, id, gconfEntry, x):
+    def _usePopupEventCallback(self, gconfClient, id, gconfEntry, x):
         self._popup = gconfEntry.get_value().get_bool()
 
 
 if __name__ == "__main__":
         self._popup = gconfEntry.get_value().get_bool()
 
 
 if __name__ == "__main__":
-    d = Daemon(Launcher(), Settings(), gtk.Window())
+    d = Daemon(Launcher(), ApplicationSettings(), NetworkSettings(), gtk.Window())
  
     d.start()
     d.stop()
  
     d.start()
     d.stop()
index f8dbb5d..721c33a 100644 (file)
@@ -10,8 +10,18 @@ class Launcher():
         pass
     
     # ---- public API __________________________________________________________
         pass
     
     # ---- public API __________________________________________________________
+    
+    def launchBrowser(self, browser_name, browser_options):
+        """Uses the specified browser and makes the calls specified in the browser_options"""
+        # TODO: 
+        
+        url = browser_options['url']
+        self.openUrl(url)
 
 
+    
     def openUrl(self, url):
     def openUrl(self, url):
+        """Uses the default browser to open the specified url."""
+        
         osso_context = osso.Context("org.maemo.touchsearch", "1.1", False)
         osso_rpc = osso.Rpc(osso_context)
         osso_rpc.rpc_run_with_defaults("osso_browser", "open_new_window", (url,))
         osso_context = osso.Context("org.maemo.touchsearch", "1.1", False)
         osso_rpc = osso.Rpc(osso_context)
         osso_rpc.rpc_run_with_defaults("osso_browser", "open_new_window", (url,))
diff --git a/package/src/wifi_assistant/settings/ApplicationSettings.py b/package/src/wifi_assistant/settings/ApplicationSettings.py
new file mode 100644 (file)
index 0000000..ff161a2
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/python2.5
+from gnome import gconf
+
+class ApplicationSettings():
+    
+    def __init__(self, gconf_client, gconf_root_dir='/apps/maemo/wifi-assistant'):
+        self._gc = gconf_client
+        self._gconfRootDir = gconf_root_dir
+        self._gconfPopupKey = gconf_root_dir + '/daemon'
+        self._listeners = {}
+    
+    # ---- public API __________________________________________________________
+        
+    def registerUsePopupListener(self, callback):
+        """Registers a listener/callback to changes on Use Daemon setting"""
+        
+        if len(self._listeners) == 0:
+            self._gc.add_dir(self._gconfRootDir, gconf.CLIENT_PRELOAD_NONE)
+        ref_id = self._gc.notify_add(self._gconfPopupKey, callback)
+        self._listeners[callback] = ref_id
+        
+    
+    def unregisterUsePopupListener(self, callback):
+        """Unregisters the listener/callback"""
+        
+        if (self._listeners.has_key(callback)):
+            ref_id = self._listeners.pop(callback)
+            self._gc.notify_remove(ref_id)
+            
+            if len(self._listeners) == 0:
+                self._gc.remove_dir(self._gconfRootDir)
+    
+            
+    def getUsePopup(self):
+        """Tells whether to use the daemon or not."""
+        
+        return self._gc.get_bool(self._gconfPopupKey) is True
+
+
+    def setUsePopup(self, mode):
+        """mode is either True or False."""
+        
+        self._gc.set_bool(self._gconfPopupKey, mode)
diff --git a/package/src/wifi_assistant/settings/NetworkSetting.py b/package/src/wifi_assistant/settings/NetworkSetting.py
new file mode 100644 (file)
index 0000000..065face
--- /dev/null
@@ -0,0 +1,49 @@
+
+class NetworkSetting(object):
+    '''
+    The settings specified for a network
+    '''
+
+    def __init__(self, settings=None):
+        self._attributes = {}
+        if (settings):
+            for key in settings:
+                self._attributes[key] = settings[key]
+        if not self._attributes.has_key('launch'):
+            self.setLaunchingOfBrowserEnabled(False)
+    
+    def getNetworkName(self):
+        return self._attributes['name']
+    
+    
+    def setNetworkName(self, name):
+        self._attributes['name'] = name
+        
+        
+    def getLaunchingOfBrowserEnabled(self):
+        return self._attributes['launch'] is True
+        
+        
+    def setLaunchingOfBrowserEnabled(self, value):
+        self._attributes['launch'] = value
+        
+        
+    def getNameOfBrowserToLaunch(self):
+        if self._attributes.has_key('browser'):
+            return self._attributes['browser']
+        return "default"
+    
+    
+    def setNameOfBrowserToLaunch(self, browser):
+        self._attributes['browser'] = browser
+    
+    
+    def getBrowserOptions(self):
+        if self._attributes.has_key('options'):
+            return self._attributes['options']
+        return {}
+    
+    
+    def setBrowserOptions(self, options):
+        self._attributes['options'] = options
+    
\ No newline at end of file
diff --git a/package/src/wifi_assistant/settings/NetworkSettings.py b/package/src/wifi_assistant/settings/NetworkSettings.py
new file mode 100644 (file)
index 0000000..0eacaeb
--- /dev/null
@@ -0,0 +1,133 @@
+import gnome.gconf as gconf
+from NetworkSetting import NetworkSetting
+import gtk, gobject
+
+
+class NetworkSettings(object):
+    '''
+    Reads and Writes NetworkSettings from/to GConf.
+    '''
+
+    __DEFAULT_SETTINGS = 'default_settings'
+    
+    def __init__(self, gconf_client, root_path):
+        self._gc = gconf_client
+        self._root_path = root_path
+        
+    
+    def delete(self, launch_setting):
+        key = self._assembleRootKeyForSsid(launch_setting.getNetworkName())
+        self._recursive_unset(key)
+        
+        
+    def getDefaultSettings(self):
+        settings = self.get(self.__DEFAULT_SETTINGS)
+        if settings is None:
+            settings = NetworkSetting()
+            settings.setNetworkName(self.__DEFAULT_SETTINGS)
+            settings.setLaunchingOfBrowserEnabled(True)
+            settings.setBrowserOptions({'url':'http://wifi-assistant.garage.maemo.org/'})
+            self.save(settings)
+        return settings
+    
+
+    def getListStore(self):
+        """Returns a ListStore with one Row per Network Setting"""
+
+        store = gtk.ListStore(str, gobject.TYPE_BOOLEAN)
+        settings = self._getAllNetworkSettings()
+        for setting in settings:
+            store.append([setting.getNetworkName(), setting.getLaunchingOfBrowserEnabled()])
+        return store
+    
+
+    def get(self, ssid):
+        key = self._assembleRootKeyForSsid(ssid)
+        if self._gc.dir_exists(key):
+            return NetworkSetting(self._loadValuesFromGConf(key))
+        print "WARNING: No settings to return for network name", ssid
+        return None
+    
+    
+    def save(self, launch_setting):
+        self._saveValuesToGConf(launch_setting)
+    
+    
+    def _assembleRootKeyForSsid(self, ssid):
+        safe = self._replaceForbiddenCharacters(ssid)
+        return self._root_path + '/' + safe
+    
+    
+    def _getAllNetworkSettings(self):
+        dirs = self._gc.all_dirs(self._root_path)
+        settings = []
+        key_offset = len(self._root_path) + 1
+        for dir in dirs:
+            key = dir[key_offset:]
+            if self.__DEFAULT_SETTINGS != key:
+                settings.append(self.get(key))
+        return settings
+    
+    
+    def _loadValuesFromGConf(self, path):
+        """Loads all values under a given path in gconf recursively into a dict"""
+        
+        values = {}
+        path_length = len(path) + 1 # remove trailing / too
+        
+        dirs = self._gc.all_dirs(path)
+        for sub_dir_path in dirs:
+            key = sub_dir_path[path_length:]
+            values[key] = self._loadValuesFromGConf(sub_dir_path)
+        
+        entries = self._gc.all_entries(path)
+        for entry in entries:
+            full_key = entry.get_key()
+            key = full_key[path_length:]
+            gvalue = entry.get_value()
+            if gvalue.type == gconf.VALUE_BOOL:
+                values[key] = gvalue.get_bool()
+            elif gvalue.type == gconf.VALUE_STRING:
+                values[key] = gvalue.get_string()
+            else:
+                print 'ga'
+        
+        return values
+    
+    
+    def _recursive_unset(self, dir):
+        # there's no recursive_unset available in gconf so we'll have to do it ourselves
+        all_entries = self._gc.all_entries(dir)
+        for entry in all_entries:
+            self._gc.unset(entry.get_key())
+        for sub_dir in self._gc.all_dirs(dir):
+            self._recursive_unset(sub_dir)
+        self._gc.suggest_sync()
+
+    
+    def _replaceForbiddenCharacters(self, str):
+        allowed = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_'
+        result = ''
+        for c in str:
+            if c in allowed:
+                result = result + c
+            else:
+                result = result + '__'
+        return result
+    
+    
+    def _saveValuesToGConf(self, launch_setting):
+        """Saves all values "recursively" from NetworkSetting"""
+        
+        network_name = launch_setting.getNetworkName()
+        key = self._assembleRootKeyForSsid(network_name)
+        browser = launch_setting.getNameOfBrowserToLaunch()
+        launch = launch_setting.getLaunchingOfBrowserEnabled()
+        options = launch_setting.getBrowserOptions()
+        
+        self._gc.set_string(key + "/name", network_name)
+        self._gc.set_string(key + '/browser', browser)
+        self._gc.set_bool(key + '/launch', launch)
+        for option_key in options:
+            self._gc.set_string(key + "/options/" + option_key, options[option_key])
+        
\ No newline at end of file
diff --git a/package/test/unit/settings/__init__.py b/package/test/unit/settings/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/package/test/unit/settings/test_ApplicationSettings.py b/package/test/unit/settings/test_ApplicationSettings.py
new file mode 100644 (file)
index 0000000..354c3f0
--- /dev/null
@@ -0,0 +1,75 @@
+from gnome import gconf
+from wifi_assistant.settings.ApplicationSettings import ApplicationSettings
+
+import unittest
+
+class ApplicationSettingsTest(unittest.TestCase):
+
+    def setUp(self):
+        self.gc = gconf.client_get_default()
+        self.root = '/apps/maemo/wifi/unit_tests'
+        self._clearGConf(self.root)
+        self._setupDefaultValues(self.root)
+        self._firstCallbackCalled = None
+        self._secondCallbackCalled = None
+        self.testee = ApplicationSettings(self.gc, self.root)
+        
+    def _setupDefaultValues(self, dir):
+        self.gc.set_bool(dir + '/daemon', True)
+
+    # FIXME: inherit
+    def _clearGConf(self, dir):
+        # there's no recursive_unset available
+        all_entries = self.gc.all_entries(dir)
+        for entry in all_entries:
+            self.gc.unset(entry.get_key())
+        for sub_dir in self.gc.all_dirs(dir):
+            self._clearGConf(sub_dir)
+        self.gc.suggest_sync()
+        
+
+    def test_default_is_to_use_popup(self):
+        assert self.testee.getUsePopup() is True
+    
+    
+    def test_setting_use_popup_works(self):
+        assert self.testee.getUsePopup() is True
+
+        self.testee.setUsePopup(False)
+        assert self.testee.getUsePopup() is False
+
+        self.testee.setUsePopup(True)
+        assert self.testee.getUsePopup() is True
+        
+    
+    def dont_test_adding_two_listeners_removing_one_still_notifies_first_listener(self):
+        firstSignal = False
+        secondSignal = True
+        
+        self.testee.registerUsePopupListener(self._firstCallback)
+        self.testee.registerUsePopupListener(self._secondCallback)
+        
+        # TODO: start thread to have signalling work properly ... 
+        
+        self.testee.setUsePopup(firstSignal)
+        
+        assert self._firstCallbackCalled == firstSignal
+        assert self._secondCallbackCalled == firstSignal
+    
+        self.testee.unregisterUsePopupListener(self._secondCallback)
+        self.testee.setUsePopup(secondSignal)
+        
+        assert self._firstCallbackCalled == secondSignal
+        assert self._secondCallbackCalled == firstSignal
+        
+    
+    def _firstCallback(self, value):
+        self._firstCallbackCalled = value
+        
+    def _secondCallback(self, value):
+        self._secondCallbackCalled = value
+    
+    
+if __name__ == '__main__':
+    unittest.main()
+
diff --git a/package/test/unit/settings/test_NetworkSettings.py b/package/test/unit/settings/test_NetworkSettings.py
new file mode 100644 (file)
index 0000000..1db0aa6
--- /dev/null
@@ -0,0 +1,110 @@
+from gnome import gconf
+from wifi_assistant.settings.NetworkSettings import NetworkSettings
+from wifi_assistant.settings.NetworkSetting import NetworkSetting
+
+import unittest
+
+class NetworkSettingsTest(unittest.TestCase):
+
+    def setUp(self):
+        self.gc = gconf.client_get_default()
+        self.root = '/apps/maemo/wifi/unit_tests'
+        self._clearGConf(self.root)
+        self._setupDefaultValues(self.root)
+        self.testee = NetworkSettings(self.gc, self.root)
+        
+    def _setupDefaultValues(self, dir):
+        #settings = NetworkSetting()
+        #settings.setBrowserOption("url", "http://wifi-assistant.wendt.se/")
+        #settings.setNameOfBrowserToLaunch("default")
+        #settings.setNetworkName("default_settings")
+        #self.testee.save(settings)
+        #self.gc.set_string(dir + '/default_settings/options/url', 'http://wifi-assistant.wendt.se/')
+        #self.gc.set_string(dir + '/default_settings/browser', 'default')
+        # moved this into code for now
+        return
+        
+    def _clearGConf(self, dir):
+        # there's no recursive_unset available
+        all_entries = self.gc.all_entries(dir)
+        for entry in all_entries:
+            self.gc.unset(entry.get_key())
+        for sub_dir in self.gc.all_dirs(dir):
+            self._clearGConf(sub_dir)
+        self.gc.suggest_sync()
+        
+
+    def _createSettings(self, ssid):
+        return NetworkSetting({'name':ssid})
+
+
+    def test_an_unkown_ssid_returns_None(self):
+        settings = self.testee.get('unknown')
+        assert settings is None
+        
+    
+    def test_saving_works(self):
+        ssid = 'test'
+        settings = self._createSettings(ssid)
+        
+         # make sure it's empty first
+        assert self.testee.get(ssid) is None
+        
+        self.testee.save(settings)
+        assert self.testee.get(ssid) is not None
+        
+        
+    def test_removing_network_setting_works(self):
+        ssid = 'test'
+        settings = self._createSettings(ssid)
+        
+         # make sure it's empty first
+        assert self.testee.get(ssid) is None
+        
+        self.testee.save(settings)
+        assert self.testee.get(ssid) is not None
+
+        self.testee.delete(settings)
+        value =  self.testee.get(ssid)
+        assert value is None
+        
+    
+    def test_network_name_can_contain_space_dash_and_underscore(self):
+        ssid = 'This Is-My_Network'
+        settings = self._createSettings(ssid)
+        
+         # make sure it's empty first
+        assert self.testee.get(ssid) is None
+        
+        self.testee.save(settings)
+        value = self.testee.get(ssid)
+        assert value is not None
+        assert value.getNetworkName() == ssid
+        
+        
+    def test_default_settings(self):
+        defaults = self.testee.getDefaultSettings()
+        assert defaults.getNameOfBrowserToLaunch() == 'default'
+        browser_options = defaults.getBrowserOptions()
+        assert defaults.getLaunchingOfBrowserEnabled() is True
+        assert browser_options is not None
+        assert browser_options.has_key('url')
+        assert "http://" in browser_options['url']
+        
+        
+    def test_list(self):
+        ssid = 'This Is-My_Network'
+        settings = self._createSettings(ssid)
+        self.testee.save(settings)
+        
+        store = self.testee.getListStore()
+        assert store is not None
+        store_len = len(store)
+        assert store_len == 1
+        
+        # FIXME: assert that default_settings are not there
+
+
+if __name__ == '__main__':
+    unittest.main()
+
diff --git a/package/test/unit/test_Daemon.py b/package/test/unit/test_Daemon.py
new file mode 100644 (file)
index 0000000..9e7555b
--- /dev/null
@@ -0,0 +1,97 @@
+from gnome import gconf
+from wifi_assistant.daemon import Daemon
+from wifi_assistant.settings.NetworkSetting import NetworkSetting
+
+import unittest
+from pie import *
+
+url_to_open = 'http://wifi-assistant.garage.maemo.org'
+default_browser_name = "default"
+default_browser_options = {'url':url_to_open}
+default_settings = NetworkSetting()
+default_settings.setNameOfBrowserToLaunch(default_browser_name)
+default_settings.setBrowserOptions(default_browser_options)
+ssid = 'A Network Name'
+settings_without_options = NetworkSetting()
+settings_without_options.setNetworkName(ssid)
+settings_without_options.setLaunchingOfBrowserEnabled(True)
+
+class DaemonTest(unittest.TestCase):
+
+    def replayMocks(self):
+        self.application_settings.replay()
+        self.launcher.replay()
+        self.network_settings.replay()
+
+    def setUp(self):
+        self.launcher = Mock()
+        self.application_settings = Mock()
+        self.network_settings = Mock()
+        self.parent_window = None
+        
+    def createTesteeWithPopupClickingYes(self):
+        given(self.application_settings).getUsePopup().willReturn(True)
+        self.testee = Daemon(self.launcher, self.application_settings, self.network_settings, self.parent_window)
+        
+        def yes(*args, **kwargs):
+            return True
+        self.testee.showDecisionDialog = yes
+
+    def createTesteeWithPopupClickingNo(self):
+        given(self.application_settings).getUsePopup().willReturn(True)
+        self.testee = Daemon(self.launcher, self.application_settings, self.network_settings, self.parent_window)
+        
+        def no(*args, **kwargs):
+            return False
+        self.testee.showDecisionDialog = no
+
+    def test_withANewNetwork_whenUserClicksYes_browserIsLaunched(self):
+        # GIVEN
+        self.createTesteeWithPopupClickingYes()
+        given(self.network_settings).get(ssid).willReturn(None)
+        given(self.network_settings).getDefaultSettings().willReturn(default_settings)
+        
+        # WHEN
+        self.replayMocks()
+        self.testee.connectionEstablished(ssid)
+        
+        # THEN
+        verify(self.network_settings).getDefaultSettings()
+        verify(self.launcher).launchBrowser(default_browser_name, default_browser_options)
+        
+    def test_withANewNetwork_whenUserClicksNo_browserIsNotLaunched(self):
+        self.createTesteeWithPopupClickingNo()
+        given(self.network_settings).get(ssid).willReturn(None)
+
+        # WHEN
+        self.replayMocks()
+        self.testee.connectionEstablished(ssid)
+        
+        # THEN
+        verify(self.launcher, never()).launchBrowser(default_browser_name, default_browser_options)
+    
+    def test_popupIsNotOpenedIfPopupIsDisabledInApplicationSettings(self):
+        given(self.application_settings).getUsePopup().willReturn(False)
+        self.testee = Daemon(self.launcher, self.application_settings, self.network_settings, self.parent_window)
+        
+        self.replayMocks()
+        self.testee.connectionEstablished(ssid)
+        
+        verify(self.launcher, never()).launchBrowser()
+        verify(self.network_settings, never()).get(ssid)
+    
+    def test_knownSsidWithLaunchSetToTrueUsesDefaultBrowserAndUrl(self):
+        given(self.network_settings).get(ssid).willReturn(settings_without_options)
+        given(self.network_settings).getDefaultSettings().willReturn(default_settings)
+        given(self.application_settings).getUsePopup().willReturn(True)
+        self.testee = Daemon(self.launcher, self.application_settings, self.network_settings, self.parent_window)
+        
+        self.replayMocks()
+        self.testee.connectionEstablished(ssid)
+        
+        verify(self.launcher, never()).launchBrowser(default_browser_name, default_browser_options)
+
+    
+if __name__ == '__main__':
+    unittest.main()
+