"""Remote-control interfaces to some browsers.""" import os import string import sys DEFAULT_CONFIG_FILE = "~/.browser.ini" PROCESS_CREATION_DELAY = 4 DEFAULT_BROWSER = "netscape" _browsers = {} def get(name=None): if name is None: name = get_default_browser() else: name = string.lower(name) L = _browsers[name] if L[1] is None: L[1] = L[0]() return L[1] def get_default_browser(file=None): if file is None: files = [DEFAULT_CONFIG_FILE] else: files = [file, DEFAULT_CONFIG_FILE] for file in files: file = os.path.expandvars(os.path.expanduser(file)) if file and os.path.isfile(file): import ConfigParser cf = ConfigParser.ConfigParser() cf.read([file]) try: return string.lower(cf.get("Browser", "name")) except ConfigParser.Error: pass return DEFAULT_BROWSER _default_browser = None def _get_browser(): global _default_browser if _default_browser is None: _default_browser = get() return _default_browser def open(url, new=0): _get_browser().open(url, new) def open_new(url): _get_browser().open_new(url) def register(name, klass): _browsers[string.lower(name)] = [klass, None] class Netscape: autoRaise = 0 def _remote(self, action): raise_opt = ("-noraise", "-raise")[self.autoRaise] cmd = "netscape %s -remote '%s' >/dev/null 2>&1" % (raise_opt, action) rc = os.system(cmd) if rc: import time os.system("netscape -no-about-splash &") time.sleep(PROCESS_CREATION_DELAY) rc = os.system(cmd) return not rc def open(self, url, new=0): if new: self.open_new(url) else: self._remote("openURL(%s)" % url) def open_new(self, url): self._remote("openURL(%s, new-window)" % url) register("netscape", Netscape) class Grail: # There should be a way to maintain a connection to Grail, but the # Grail remote control protocol doesn't really allow that at this # point. It probably never will! def _find_grail_rc(self): import glob import pwd import socket import tempfile tempdir = os.path.join(tempfile.gettempdir(), ".grail-unix") user = pwd.getpwuid(_os.getuid())[0] filename = os.path.join(tempdir, user + "-*") maybes = glob.glob(filename) if not maybes: return None s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) for fn in maybes: # need to PING each one until we find one that's live try: s.connect(fn) except socket.error: # no good; attempt to clean it out, but don't fail: try: os.unlink(fn) except IOError: pass else: return s def _remote(self, action): s = self._find_grail_rc() if not s: return 0 s.send(action) s.close() return 1 def open(self, url, new=0): if new: self.open_new(url) else: self._remote("LOAD " + url) def open_new(self, url): self._remote("LOADNEW " + url) register("grail", Grail) class WindowsDefault: def open(self, url, new=0): import win32api, win32con try: win32api.ShellExecute(0, "open", url, None, ".", win32con.SW_SHOWNORMAL) except: traceback.print_exc() raise def open_new(self, url): self.open(url) if sys.platform[:3] == "win": register("windows-default", WindowsDefault) DEFAULT_BROWSER = "windows-default"