blob: 3829d49dc9b2ae8d810f8eaa841804f0a8568f85 [file] [log] [blame]
Fred Drake95a40002000-05-10 16:47:27 +00001"""Remote-control interfaces to some browsers."""
2
3import os
4import string
5import sys
6
7
8DEFAULT_CONFIG_FILE = "~/.browser.ini"
9PROCESS_CREATION_DELAY = 4
10
11DEFAULT_BROWSER = "netscape"
12
13_browsers = {}
14
15
16def get(name=None):
17 if name is None:
18 name = get_default_browser()
19 else:
20 name = string.lower(name)
21 L = _browsers[name]
22 if L[1] is None:
23 L[1] = L[0]()
24 return L[1]
25
26
27def get_default_browser(file=None):
28 if file is None:
29 files = [DEFAULT_CONFIG_FILE]
30 else:
31 files = [file, DEFAULT_CONFIG_FILE]
32 for file in files:
33 file = os.path.expandvars(os.path.expanduser(file))
34 if file and os.path.isfile(file):
35 import ConfigParser
36 cf = ConfigParser.ConfigParser()
37 cf.read([file])
38 try:
39 return string.lower(cf.get("Browser", "name"))
40 except ConfigParser.Error:
41 pass
42 return DEFAULT_BROWSER
43
44
45_default_browser = None
46
47def _get_browser():
48 global _default_browser
49 if _default_browser is None:
50 _default_browser = get()
51 return _default_browser
52
53
54def open(url, new=0):
55 _get_browser().open(url, new)
56
57
58def open_new(url):
59 _get_browser().open_new(url)
60
61
62def register(name, klass):
63 _browsers[string.lower(name)] = [klass, None]
64
65
66class Netscape:
67 autoRaise = 0
68
69 def _remote(self, action):
70 raise_opt = ("-noraise", "-raise")[self.autoRaise]
71 cmd = "netscape %s -remote '%s' >/dev/null 2>&1" % (raise_opt, action)
72 rc = os.system(cmd)
73 if rc:
74 import time
75 os.system("netscape -no-about-splash &")
76 time.sleep(PROCESS_CREATION_DELAY)
77 rc = os.system(cmd)
78 return not rc
79
80 def open(self, url, new=0):
81 if new:
82 self.open_new(url)
83 else:
84 self._remote("openURL(%s)" % url)
85
86 def open_new(self, url):
87 self._remote("openURL(%s, new-window)" % url)
88
89register("netscape", Netscape)
90
91
92class Grail:
93 # There should be a way to maintain a connection to Grail, but the
94 # Grail remote control protocol doesn't really allow that at this
95 # point. It probably never will!
96
97 def _find_grail_rc(self):
98 import glob
99 import pwd
100 import socket
101 import tempfile
102 tempdir = os.path.join(tempfile.gettempdir(), ".grail-unix")
103 user = pwd.getpwuid(_os.getuid())[0]
104 filename = os.path.join(tempdir, user + "-*")
105 maybes = glob.glob(filename)
106 if not maybes:
107 return None
108 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
109 for fn in maybes:
110 # need to PING each one until we find one that's live
111 try:
112 s.connect(fn)
113 except socket.error:
114 # no good; attempt to clean it out, but don't fail:
115 try:
116 os.unlink(fn)
117 except IOError:
118 pass
119 else:
120 return s
121
122 def _remote(self, action):
123 s = self._find_grail_rc()
124 if not s:
125 return 0
126 s.send(action)
127 s.close()
128 return 1
129
130 def open(self, url, new=0):
131 if new:
132 self.open_new(url)
133 else:
134 self._remote("LOAD " + url)
135
136 def open_new(self, url):
137 self._remote("LOADNEW " + url)
138
139register("grail", Grail)
140
141
142class WindowsDefault:
143 def open(self, url, new=0):
144 import win32api, win32con
145 try:
146 win32api.ShellExecute(0, "open", url, None, ".",
147 win32con.SW_SHOWNORMAL)
148 except:
149 traceback.print_exc()
150 raise
151
152 def open_new(self, url):
153 self.open(url)
154
155if sys.platform[:3] == "win":
156 register("windows-default", WindowsDefault)
157 DEFAULT_BROWSER = "windows-default"