Mercurial > libervia-web
comparison src/browser/sat_browser/plugin_sec_otr.py @ 665:6a8a1103ad10 frontends_multi_profiles
browser_side: OTR uses 'profilePlugged', 'disconnect' and 'gotMenus' listeners
author | souliane <souliane@mailoo.org> |
---|---|
date | Tue, 03 Mar 2015 22:31:54 +0100 |
parents | 8449a5db0602 |
children | 849ffb24d5bf |
comparison
equal
deleted
inserted
replaced
664:8449a5db0602 | 665:6a8a1103ad10 |
---|---|
357 if start: | 357 if start: |
358 return self.startContext(other_jid) | 358 return self.startContext(other_jid) |
359 else: | 359 else: |
360 return self.contexts.get(other_jid, None) | 360 return self.contexts.get(other_jid, None) |
361 | 361 |
362 def getContextsForBareUser(self, bare_jid): | |
363 """Get all the contexts for the users sharing the given bare JID. | |
364 | |
365 @param bare_jid (jid.JID): bare JID | |
366 @return: list[Context] | |
367 """ | |
368 return [context for other_jid, context in self.contexts.iteritems() if other_jid.bare == bare_jid] | |
369 | |
362 def fixResource(self, other_jid): | 370 def fixResource(self, other_jid): |
363 """Return the full JID in case the resource of the given JID is missing. | 371 """Return the full JID in case the resource of the given JID is missing. |
364 | 372 |
365 @param other_jid (jid.JID): JID to check | 373 @param other_jid (jid.JID): JID to check |
366 @return jid.JID | 374 @return jid.JID |
381 self.context_manager = None | 389 self.context_manager = None |
382 self.host.bridge._registerMethods(["skipOTR"]) | 390 self.host.bridge._registerMethods(["skipOTR"]) |
383 self.host.trigger.add("newMessageTrigger", self.newMessageTg, priority=TriggerManager.MAX_PRIORITY) | 391 self.host.trigger.add("newMessageTrigger", self.newMessageTg, priority=TriggerManager.MAX_PRIORITY) |
384 self.host.trigger.add("sendMessageTrigger", self.sendMessageTg, priority=TriggerManager.MAX_PRIORITY) | 392 self.host.trigger.add("sendMessageTrigger", self.sendMessageTg, priority=TriggerManager.MAX_PRIORITY) |
385 | 393 |
394 # FIXME: workaround for a pyjamas issue: calling hash on a class method always return a different value if that method is defined directly within the class (with the "def" keyword) | |
395 self._profilePluggedListener = self.profilePluggedListener | |
396 self._gotMenusListener = self.gotMenusListener | |
397 # FIXME: these listeners are never removed, can't be removed by themselves (it modifies the list while looping), maybe need a 'one_shot' argument | |
398 self.host.addListener('profilePlugged', self._profilePluggedListener) | |
399 self.host.addListener('gotMenus', self._gotMenusListener) | |
400 | |
386 @classmethod | 401 @classmethod |
387 def getInfoText(self, state=otr.context.STATE_PLAINTEXT, trust=''): | 402 def getInfoText(self, state=otr.context.STATE_PLAINTEXT, trust=''): |
388 """Get the widget info text for a certain message state and trust. | 403 """Get the widget info text for a certain message state and trust. |
389 | 404 |
390 @param state (unicode): message state | 405 @param state (unicode): message state |
404 if otrctx is None: | 419 if otrctx is None: |
405 return OTR.getInfoText() | 420 return OTR.getInfoText() |
406 else: | 421 else: |
407 return OTR.getInfoText(otrctx.state, otrctx.getCurrentTrust()) | 422 return OTR.getInfoText(otrctx.state, otrctx.getCurrentTrust()) |
408 | 423 |
409 def inhibitMenus(self): | 424 def gotMenusListener(self, menus, profile): |
410 """Tell the caller which dynamic menus should be inhibited""" | 425 menus_to_delete = [] |
411 return ["OTR"] # menu categories name to inhibit | 426 for menu in menus: |
412 | 427 id_, type_, path, path_i18n = menu |
413 def extraMenus(self): | 428 if path[0] == 'OTR': |
429 menus_to_delete.append(menu) | |
430 for menu in menus_to_delete: | |
431 menus.remove(menu) | |
414 # FIXME: handle help strings too | 432 # FIXME: handle help strings too |
415 return [(self._startRefresh, C.MENU_SINGLE, (MAIN_MENU, "Start / refresh"), (MAIN_MENU, D_("Start / refresh"))), | 433 menus.extend([(self._startRefresh, C.MENU_SINGLE, (MAIN_MENU, "Start / refresh"), (MAIN_MENU, D_("Start / refresh"))), |
416 (self._endSession, C.MENU_SINGLE, (MAIN_MENU, "Stop encryption"), (MAIN_MENU, D_("Stop encryption"))), | 434 (self._endSession, C.MENU_SINGLE, (MAIN_MENU, "Stop encryption"), (MAIN_MENU, D_("Stop encryption"))), |
417 (self._authenticate, C.MENU_SINGLE, (MAIN_MENU, "Authenticate correspondent"), (MAIN_MENU, D_("Authenticate correspondent"))), | 435 (self._authenticate, C.MENU_SINGLE, (MAIN_MENU, "Authenticate correspondent"), (MAIN_MENU, D_("Authenticate correspondent"))), |
418 (self._dropPrivkey, C.MENU_SINGLE, (MAIN_MENU, "Drop your private key"), (MAIN_MENU, D_("Drop your private key")))] | 436 (self._dropPrivkey, C.MENU_SINGLE, (MAIN_MENU, "Drop your private key"), (MAIN_MENU, D_("Drop your private key"))), |
419 | 437 ]) |
420 def profileConnected(self): | 438 |
439 def profilePluggedListener(self, profile): | |
440 # FIXME: workaround for a pyjamas issue: calling hash on a class method always return a different value if that method is defined directly within the class (with the "def" keyword) | |
441 self._presenceListener = self.presenceListener | |
442 self._disconnectListener = self.disconnectListener | |
443 self.host.addListener('presence', self._presenceListener, [C.PROF_KEY_NONE]) | |
444 # FIXME: this listener is never removed, can't be removed by itself (it modifies the list while looping), maybe need a 'one_shot' argument | |
445 self.host.addListener('disconnect', self._disconnectListener, [C.PROF_KEY_NONE]) | |
446 | |
421 self.host.bridge.call('skipOTR', None) | 447 self.host.bridge.call('skipOTR', None) |
422 self.context_manager = ContextManager(self.host) | 448 self.context_manager = ContextManager(self.host) |
423 # TODO: retrieve the encrypted private key from a HTML5 persistent storage, | 449 # TODO: retrieve the encrypted private key from a HTML5 persistent storage, |
424 # decrypt it, parse it with otr.crypt.PK.parsePrivateKey(privkey) and | 450 # decrypt it, parse it with otr.crypt.PK.parsePrivateKey(privkey) and |
425 # assign it to self.context_manager.account.privkey | 451 # assign it to self.context_manager.account.privkey |
426 | 452 |
427 # FIXME: workaround for a pyjamas issue: calling hash on a class method always return a different value if that method is defined directly within the class (with the "def" keyword) | 453 def disconnectListener(self, profile): |
428 self.presenceListener = self.onPresenceUpdate | 454 """Things to do just before the profile disconnection""" |
429 self.host.addListener('presence', self.presenceListener, [C.PROF_KEY_NONE]) | 455 self.host.removeListener('presence', self._presenceListener) |
430 | 456 |
431 def profileDisconnected(self): | |
432 for context in self.context_manager.contexts.values(): | 457 for context in self.context_manager.contexts.values(): |
433 context.disconnect() | 458 context.disconnect() # FIXME: no time to send the message before the profile has been disconnected |
434 self.host.removeListener('presence', self.presenceListener) | 459 |
460 def presenceListener(self, entity, show, priority, statuses, profile): | |
461 if show == C.PRESENCE_UNAVAILABLE: | |
462 self.endSession(entity, disconnect=False) | |
435 | 463 |
436 def newMessageTg(self, from_jid, msg, msg_type, to_jid, extra, profile): | 464 def newMessageTg(self, from_jid, msg, msg_type, to_jid, extra, profile): |
437 if msg_type != C.MESS_TYPE_CHAT: | 465 if msg_type != C.MESS_TYPE_CHAT: |
438 return True | 466 return True |
439 | 467 |
475 return False # interrupt the main process | 503 return False # interrupt the main process |
476 | 504 |
477 log.debug(u"sending message unencrypted") | 505 log.debug(u"sending message unencrypted") |
478 return True | 506 return True |
479 | 507 |
480 def onPresenceUpdate(self, entity, show, priority, statuses, profile): | 508 def endSession(self, other_jid, disconnect=True): |
481 if show == C.PRESENCE_UNAVAILABLE: | |
482 self.endSession(entity, finish=True) | |
483 | |
484 def endSession(self, other_jid, finish=False): | |
485 """Finish or disconnect an OTR session | 509 """Finish or disconnect an OTR session |
486 | 510 |
487 @param other_jid (jid.JID): other JID | 511 @param other_jid (jid.JID): other JID |
488 @param finish: if True, finish the session but do not disconnect it | 512 @param disconnect (bool): if False, finish the session but do not disconnect it |
489 @return: True if the session has been finished or disconnected, False if there was nothing to do | |
490 """ | 513 """ |
491 # checking for private key existence is not needed, context checking is enough | 514 # checking for private key existence is not needed, context checking is enough |
492 otrctx = self.context_manager.getContextForUser(other_jid, start=False) | 515 if other_jid.resource: |
493 if otrctx is None or otrctx.state == otr.context.STATE_PLAINTEXT: | 516 contexts = [self.context_manager.getContextForUser(other_jid, start=False)] |
494 if not finish: | 517 else: # contact disconnected itself so we need to terminate the OTR session but the Chat panel lost its resource |
495 self.host.newMessageHandler(unicode(other_jid), END_PLAIN_HAS_NOT.format(jid=other_jid), C.MESS_TYPE_INFO, unicode(self.host.whoami), {}) | 518 contexts = self.context_manager.getContextsForBareUser(other_jid) |
496 return | 519 for otrctx in contexts: |
497 if finish: | 520 if otrctx is None or otrctx.state == otr.context.STATE_PLAINTEXT: |
498 otrctx.finish() | 521 if disconnect: |
499 else: | 522 self.host.newMessageHandler(unicode(other_jid), END_PLAIN_HAS_NOT.format(jid=other_jid), C.MESS_TYPE_INFO, unicode(self.host.whoami), {}) |
500 otrctx.disconnect() | 523 return |
524 if disconnect: | |
525 otrctx.disconnect() | |
526 else: | |
527 otrctx.finish() | |
501 | 528 |
502 # Menu callbacks | 529 # Menu callbacks |
503 | 530 |
504 def _startRefresh(self, menu_data): | 531 def _startRefresh(self, menu_data): |
505 """Start or refresh an OTR session | 532 """Start or refresh an OTR session |