diff --git a/Lib/idlelib/BrowserControl.py b/Lib/idlelib/BrowserControl.py new file mode 100755 index 00000000000..3829d49dc9b --- /dev/null +++ b/Lib/idlelib/BrowserControl.py @@ -0,0 +1,157 @@ +"""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"