From 8f8b2d04bd41dc7270c681ca7a5bcda3455b57a5 Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Wed, 4 Jul 2012 00:20:02 +0000 Subject: [PATCH] econnman: add agent support (passwords) add a very simplistic ConnMan agent when you give it --agent/-a. It will list every requested input and return those that you've filled, that simple. You can use it to enter passwords/passphrases/login whenever ConnMan requires it. Ideally this should be in e17 connman module, but until it gets there you can use this. NOTE-1: connman 1.0 has a bug that sometimes it will return "Failed I/O" even before you returned the password! NOTE-2: connman git (1.3) has a bug that it will NEVER abort Connect() calls even if the agent returns an error (is canceled). I've reported the NOTE-2 bug to their mail list and as soon as I get a reply I'll keep you informed. SVN revision: 73250 --- econnman-bin | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/econnman-bin b/econnman-bin index 9cb247c..93c8968 100755 --- a/econnman-bin +++ b/econnman-bin @@ -14,7 +14,9 @@ import elementary as elm import evas import e_dbus +import ecore import dbus +import dbus.service import logging import argparse @@ -650,6 +652,15 @@ class ServicesList(object): lb.text = "%s: %s" % (type, state) return lb + def service_name_get(self, path): + s = self.services.get(path) + if not s: + return None + n = s.get("Name") + if not n: + return None + return str(n) + class ServiceView(ObjectView): """Provides a detailed view of the service given by C{path}. @@ -1120,6 +1131,150 @@ def show_service(path, properties): nf.item_push(name, None, None, sv.obj, "basic") +######################################################################## +# Agent: +def agent_method(in_signature="", out_signature="", **kargs): + return dbus.service.method("net.connman.Agent", + in_signature=in_signature, + out_signature=out_signature, + **kargs) + +class Agent(dbus.service.Object): + path = "/org/enlightenment/econnman/agent" + + request_type_conv = { + "SSID": dbus.ByteArray, + } + + class Canceled(dbus.DBusException): + _dbus_error_name = "net.connman.Agent.Error.Canceled" + + def __init__(self, serv_lst): + dbus.service.Object.__init__(self, bus, self.path) + self.dialog = None + self.serv_lst = serv_lst + + @agent_method() + def Release(self): + log.info("Agent released by ConnMan") + if self.dialog: + self.dialog.delete() + self.dialog = None + + @agent_method(in_signature="os") + def RequestBrowser(self, path, url): + log.info("Open browser for %s at %s", path, url) + ecore.exe_run("xdg-open '%s'" % url) + + @agent_method(in_signature="os") + def ReportError(self, path, error): + log.error("ConnMan error %s: %s", path, error) + popup_error(win, "ConnMan Error", str(error)) + + @agent_method() + def Cancel(self): + log.info("Canceled dialog") + if self.dialog: + self.dialog.delete() + self.dialog = None + + @agent_method(in_signature="oa{sv}", out_signature="a{sv}", + async_callbacks=("on_done", "on_error")) + def RequestInput(self, path, fields, on_done, on_error): + log.debug("Request Input for %s: %s", path, dbus_dict_to_str(fields)) + + def on_deleted(obj): + w = self.dialog + self.dialog = None + if w: + e = Agent.Canceled("user canceled") + log.debug("User canceled agent request: %s", e) + on_error(e) + + def on_clicked(obj): + response = {} + keys = [] + for name, en in widgets.iteritems(): + conv = self.request_type_conv.get(name, dbus.String) + v = conv(en.text) + if v: + response[name] = v + keys.append(name) + log.debug("User Replies with keys: %s", ", ".join(keys)) + w = self.dialog + self.dialog = None + on_done(response) + w.delete() + + self.dialog = w = elm.Window("econnman-agent", elm.ELM_WIN_DIALOG_BASIC) + w.title = "ConnMan Requested Input" + w.icon_name = "econnman" + w.autodel = True + w.on_del_add(on_deleted) + w.show() + + bg = elm.Background(w) + bg.size_hint_weight = EXPAND_BOTH + bg.show() + w.resize_object_add(bg) + + bx = elm.Box(w) + bx.size_hint_align = FILL_BOTH + bx.horizontal = False + bx.show() + w.resize_object_add(bx) + + lb = elm.Label(bx) + lb.size_hint_weight = EXPAND_HORIZ + lb.size_hint_align = FILL_BOTH + lb.text = "ConnMan needs your input" + lb.show() + bx.pack_end(lb) + + name = self.serv_lst.service_name_get(path) + if name: + lb = elm.Label(bx) + lb.size_hint_weight = EXPAND_HORIZ + lb.size_hint_align = FILL_BOTH + lb.text = "Service: %s" % (name,) + lb.show() + bx.pack_end(lb) + + widgets = {} + for name, desc in fields.iteritems(): + decos = "" + t = desc.get("Type") + if t and t != "informational": + decos += " (type: %s)" % (t,) + if desc.get("Requirement") == "mandatory": + decos += " REQUIRED" + lb = elm.Label(bx) + lb.size_hint_weight = EXPAND_HORIZ + lb.size_hint_align = FILL_BOTH + lb.text = "%s:%s" % (name, decos) + lb.show() + bx.pack_end(lb) + + en = elm.Entry(bx) + en.size_hint_weight = EXPAND_HORIZ + en.size_hint_align = FILL_BOTH + en.single_line = True + en.scrollable = True + en.text = desc.get("Value", "") + en.editable = (t != "informational") + en.show() + bx.pack_end(en) + widgets[name] = en + + bt = elm.Button(bx) + bt.size_hint_weight = EXPAND_HORIZ + bt.size_hint_align = FILL_BOTH + bt.callback_clicked_add(on_clicked) + bt.text = "Submit" + bt.show() + bx.pack_end(bt) + + ######################################################################## # GUI helpers: def popup_fatal(obj, title, message): @@ -1139,6 +1294,7 @@ def popup_fatal(obj, title, message): bt.callback_clicked_add(lambda bt: elm.exit()) pop.part_content_set("button1", bt) pop.show() + return pop def popup_error(obj, title, message): @@ -1155,12 +1311,14 @@ def popup_error(obj, title, message): bt.callback_clicked_add(lambda bt: pop.delete()) pop.part_content_set("button1", bt) pop.show() + return pop if __name__ == "__main__": parser = argparse.ArgumentParser( description="Connection Manager for Enlightenment") parser.add_argument("-v", "--verbose", action="count") + parser.add_argument("-a", "--agent", action="store_true") args = parser.parse_args() level = logging.WARNING @@ -1207,5 +1365,11 @@ if __name__ == "__main__": nf.item_push("EConnMan", offline_mon.obj, techs, serv_lst.obj, "basic") + if args.agent: + log.debug("create agent") + agent = Agent(serv_lst) + manager.RegisterAgent(agent.path) + log.info("Registered agent at %s", agent.path) + elm.run() elm.shutdown()