import gobject
from launcher import Launcher
-from settings import Settings
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._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:
- 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)
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
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__":
- d = Daemon(Launcher(), Settings(), gtk.Window())
+ d = Daemon(Launcher(), ApplicationSettings(), NetworkSettings(), gtk.Window())
d.start()
d.stop()
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):
+ """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,))
--- /dev/null
+#!/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)
--- /dev/null
+
+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
--- /dev/null
+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
--- /dev/null
+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()
+
--- /dev/null
+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()
+
--- /dev/null
+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()
+