From a8d238b134c18477b2cf37422f2c18fccde8c242 Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Mon, 31 Aug 2009 12:17:46 +0100 Subject: [PATCH] Converted GUI handler to use new key confirmation interface The handler base class now discards queued requests that are no longer necessary. This was previously only done in the GUI. --- zeroinstall/0launch-gui/gui.py | 28 +++++++--------- zeroinstall/gtkui/trust_box.py | 71 ++++++++--------------------------------- zeroinstall/injector/handler.py | 11 +++++++ 3 files changed, 37 insertions(+), 73 deletions(-) diff --git a/zeroinstall/0launch-gui/gui.py b/zeroinstall/0launch-gui/gui.py index e9cd406..15397f8 100644 --- a/zeroinstall/0launch-gui/gui.py +++ b/zeroinstall/0launch-gui/gui.py @@ -44,25 +44,21 @@ class GUIHandler(handler.Handler): def impl_added_to_store(self, impl): self.mainwindow.update_download_status() - def confirm_trust_keys(self, interface, sigs, iface_xml): - def do_confirm(): - from zeroinstall.gtkui import trust_box - return trust_box.confirm_trust(interface, sigs, iface_xml, parent = self.mainwindow.window) + @tasks.async + def confirm_import_feed(self, pending, valid_sigs): if self.mainwindow.systray_icon: self.mainwindow.systray_icon.set_tooltip(_('Need to confirm a new GPG key')) self.mainwindow.systray_icon.set_blinking(True) - @tasks.async - def wait_and_confirm(): - # Wait for the user to click the icon, then continue - yield self.mainwindow.systray_icon_blocker - yield tasks.TimeoutBlocker(0.5, 'Delay') - conf = do_confirm() - if conf: - yield conf - return wait_and_confirm() - else: - return do_confirm() - + + # Wait for the user to click the icon, then continue + yield self.mainwindow.systray_icon_blocker + yield tasks.TimeoutBlocker(0.5, 'Delay') + + from zeroinstall.gtkui import trust_box + box = trust_box.TrustBox(pending, valid_sigs, parent = self.mainwindow.window) + box.show() + yield box.closed + def report_error(self, ex, tb = None): if isinstance(ex, download.DownloadAborted): return # No need to tell the user about this, since they caused it diff --git a/zeroinstall/gtkui/trust_box.py b/zeroinstall/gtkui/trust_box.py index 3dd498d..1ac701d 100644 --- a/zeroinstall/gtkui/trust_box.py +++ b/zeroinstall/gtkui/trust_box.py @@ -55,14 +55,16 @@ def get_hint(fingerprint): return hint_hbox class TrustBox(gtk.Dialog): - interface = None - sigs = None - iface_xml = None - valid_sigs = None + """Display a dialog box asking the user to confirm that one of the + keys is trusted for this domain. + """ parent = None closed = None - def __init__(self, interface, sigs, iface_xml, parent): + def __init__(self, pending, valid_sigs, parent): + """@since: 0.42""" + assert valid_sigs + gtk.Dialog.__init__(self) self.set_has_separator(False) self.set_position(gtk.WIN_POS_CENTER) @@ -70,53 +72,26 @@ class TrustBox(gtk.Dialog): self.closed = tasks.Blocker(_("confirming keys with user")) - domain = trust.domain_from_url(interface.uri) + domain = trust.domain_from_url(pending.url) assert domain def destroy(box): - global _queue - assert _queue[0] is self - del _queue[0] - self.closed.trigger() - # Remove any queued boxes that are no longer required - def still_untrusted(box): - for sig in box.valid_sigs: - is_trusted = trust.trust_db.is_trusted(sig.fingerprint, domain) - if is_trusted: - return False - return True - if _queue: - next = _queue[0] - if still_untrusted(next): - next.show() - else: - next.trust_keys([], domain) - next.destroy() # Will trigger this again... self.connect('destroy', destroy) - self.interface = interface - self.sigs = sigs - self.iface_xml = iface_xml - self.set_title(_('Confirm trust')) vbox = gtk.VBox(False, 4) vbox.set_border_width(4) self.vbox.pack_start(vbox, True, True, 0) - self.valid_sigs = [s for s in sigs if isinstance(s, gpg.ValidSig)] - if not self.valid_sigs: - raise SafeException(_('No valid signatures found on "%(uri)s". Signatures:%(signatures)s') % - {'uri': interface.uri, 'signatures': ''.join(['\n- ' + str(s) for s in sigs])}) - notebook = gtk.Notebook() - if len(self.valid_sigs) == 1: + if len(valid_sigs) == 1: notebook.set_show_tabs(False) - label = left(_('Checking: %s') % interface.uri) + label = left(_('Checking: %s') % pending.url) label.set_padding(4, 4) vbox.pack_start(label, False, True, 0) @@ -129,7 +104,7 @@ class TrustBox(gtk.Dialog): descriptions = [_('None')] frame(vbox, _('Keys already approved for "%s"') % domain, '\n'.join(descriptions)) - if len(self.valid_sigs) == 1: + if len(valid_sigs) == 1: label = left(_('This key signed the feed:')) else: label = left(_('These keys signed the feed:')) @@ -153,7 +128,7 @@ class TrustBox(gtk.Dialog): break self.set_response_sensitive(gtk.RESPONSE_OK, trust_any) - for sig in self.valid_sigs: + for sig in valid_sigs: if hasattr(sig, 'get_details'): name = '' details = sig.get_details() @@ -197,10 +172,10 @@ class TrustBox(gtk.Dialog): self.destroy() self.connect('response', response) - def trust_keys(self, sigs, domain): + def trust_keys(self, agreed_sigs, domain): assert domain try: - for sig in sigs: + for sig in agreed_sigs: trust.trust_db.trust_key(sig.fingerprint, domain) trust.trust_db.notify() @@ -209,24 +184,6 @@ class TrustBox(gtk.Dialog): if not isinstance(ex, SafeException): raise -_queue = [] -def confirm_trust(interface, sigs, iface_xml, parent): - """Display a dialog box asking the user to confirm that one of the - keys is trusted for this domain. If a trust box is already visible, this - one is queued until the existing one is closed. - @param interface: the feed being loaded - @type interface: L{model.Interface} - @param sigs: the signatures on the feed - @type sigs: [L{gpg.Signature}] - @param iface_xml: the downloaded (untrusted) XML document - @type iface_xml: str - """ - box = TrustBox(interface, sigs, iface_xml, parent) - _queue.append(box) - if len(_queue) == 1: - _queue[0].show() - return box.closed - trust_help = help_box.HelpBox(_("Trust Help"), (_('Overview'), '\n' + _("""When you run a program, it typically has access to all your files and can generally do \ diff --git a/zeroinstall/injector/handler.py b/zeroinstall/injector/handler.py index 99fd43f..8f93461 100644 --- a/zeroinstall/injector/handler.py +++ b/zeroinstall/injector/handler.py @@ -168,6 +168,17 @@ class Handler(object): while self._current_confirm is not None: yield self._current_confirm + # Check whether we still need to confirm. The user may have + # already approved one of the keys while dealing with another + # feed. + from zeroinstall.injector import trust + domain = trust.domain_from_url(pending.url) + for sig in valid_sigs: + is_trusted = trust.trust_db.is_trusted(sig.fingerprint, domain) + if is_trusted: + return + + # Take the lock and confirm this feed self._current_confirm = lock = tasks.Blocker('confirm key lock') try: done = self.confirm_import_feed(pending, valid_sigs) -- 2.11.4.GIT