--- webbrowser.py.41511 Fri Dec 2 15:43:59 2005 +++ webbrowser.py Thu Dec 8 15:30:58 2005 @@ -2,6 +2,7 @@ """Interfaces for launching and remotely controlling Web browsers.""" import os +import subprocess import sys import stat @@ -172,23 +173,44 @@ remote_background = False def _remote(self, url, action, autoraise): - autoraise = int(bool(autoraise)) # always 0/1 - raise_opt = self.raise_opts and self.raise_opts[autoraise] or '' - cmd = "%s %s %s '%s' >/dev/null 2>&1" % (self.name, raise_opt, - self.remote_cmd, action) - if self.remote_background: - cmd += ' &' - rc = os.system(cmd) - if rc: - cmd = "%s %s" % (self.name, url) + raise_opt = () + if self.raise_opts: + autoraise = int(bool(autoraise)) # always 0/1 + ro = self.raise_opts[autoraise] + if ro: + raise_opt = (ro,) + cmd = (self.name,) + raise_opt + (self.remote_cmd,) + action + devnull = file('/dev/null', 'r+') # or __builtin__.open + try: + p = subprocess.Popen(cmd, close_fds=True, stdin=devnull, + stdout=devnull, stderr=subprocess.STDOUT) if self.remote_background: - cmd += " &" - # bad return status, try again with simpler command - rc = os.system(cmd) + rc = 0 + else: + rc = p.wait() + except OSError: + return False + if rc: + # remote invocation failed, try again with simpler command + cmd = (self.name, url) + try: + import os + # if possible, put browser in separate process group, so + # keyboard interrupts don't affect browser as well as Python + setsid = None + if hasattr(os, 'setsid'): + setsid = os.setsid + elif hasattr(os, 'setpgrp'): + setsid = os.setpgrp + p = subprocess.Popen(cmd, close_fds=True, preexec_fn=setsid) + except OSError: + return False + # double-check that web browser hasn't immediately failed + # can never be completely sure that it started up successfully + rc = p.poll() return not rc def open(self, url, new=0, autoraise=1): - assert "'" not in url if new == 0: action = self.remote_action elif new == 1: @@ -200,7 +222,21 @@ action = self.remote_action_newtab else: raise Error("Bad 'new' parameter to open(); expected 0, 1, or 2, got %s" % new) - return self._remote(url, action % url, autoraise) + if isinstance(action, basestring): + # backwards compatibility + action = action.split() + for i, arg in enumerate(action): + if arg[0] in '\'"': + # strip leading and trailing quotes + action[i] = arg[1:-1] + actionargs = [] + for arg in action: + if '%s' in arg: + actionargs.append(arg % url) + else: + actionargs.append(arg) + ok = self._remote(url, tuple(actionargs), autoraise) + return ok class Mozilla(UnixBrowser): @@ -212,7 +248,6 @@ remote_action = "openURL(%s)" remote_action_newwin = "openURL(%s,new-window)" remote_action_newtab = "openURL(%s,new-tab)" - remote_background = True Netscape = Mozilla @@ -221,10 +256,8 @@ """Launcher class for Galeon/Epiphany browsers.""" raise_opts = ("-noraise", "") - remote_action = "-n '%s'" - remote_action_newwin = "-w '%s'" - - remote_background = True + remote_action = ("-n", "%s") + remote_action_newwin = ("-w", "%s") class Konqueror(BaseBrowser): @@ -268,7 +301,6 @@ remote_action = "openURL(%s)" remote_action_newwin = "openURL(%s,new-window)" remote_action_newtab = "openURL(%s,new-page)" - remote_background = True class Elinks(UnixBrowser):