webbrowser.py revision f79cb2db3eae59f80e8031d45376dc5f48d2af04
1f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond"""Remote-control interfaces to common browsers."""
2c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
3c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeimport os
4c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeimport sys
5c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
6c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeclass Error(Exception):
7c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    pass
8c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
9f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond_browsers = {}		# Dictionary of available browser controllers
10f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond_tryorder = []		# Preference order of available browsers
11c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
12c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakedef register(name, klass, instance=None):
13c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    """Register a browser connector and, optionally, connection."""
14c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    _browsers[name.lower()] = [klass, instance]
15c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
16f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymonddef get(using=None):
17f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    """Return a browser launcher instance appropriate for the environment."""
18f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    if using:
19f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        alternatives = [using]
20f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    else:
21f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        alternatives = _tryorder
22f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    for browser in alternatives:
23f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        if browser.find('%s') > -1:
24f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            # User gave us a command line, don't mess with it.
25f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            return browser
26f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        else:
27f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            # User gave us a browser name.
28f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            command = _browsers[browser.lower()]
29f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            if command[1] is None:
30f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                return command[0]()
31f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            else:
32f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                return command[1]
33f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    raise Error("could not locate runnable browser")
34c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
35c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake# Please note: the following definition hides a builtin function.
36c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
37f79cb2db3eae59f80e8031d45376dc5f48d2af04Eric S. Raymonddef open(url, new=0, autoraise=1):
38f79cb2db3eae59f80e8031d45376dc5f48d2af04Eric S. Raymond    get().open(url, new, autoraise)
39c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
40f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymonddef open_new(url):	# Marked deprecated.  May be removed in 2.1.
41f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    get().open(url, 1)
42c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
43f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond#
44f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# Everything after this point initializes _browsers and _tryorder,
45f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# then disappears.  Some class definitions and instances remain
46f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# live through these globals, but only the minimum set needed to
47f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# support the user's platform.
48f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond#
49c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
50f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond#
51f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# Platform support for Unix
52f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond#
53c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
54f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# This is the right test because all these Unix browsers require either
55f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# a console terminal of an X display to run.  Note that we cannot split
56f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# the TERM and DISPLAY cases, because we might be running Python from inside
57f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# an xterm.
58f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymondif os.environ.get("TERM") or os.environ.get("DISPLAY"):
59f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    PROCESS_CREATION_DELAY = 4
60f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    global tryorder
61f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    _tryorder = ("mozilla","netscape","kfm","grail","links","lynx","w3m")
62f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
63f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    def _iscommand(cmd):
64f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        """Return true if cmd can be found on the executable search path."""
65f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        path = os.environ.get("PATH")
66f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        if not path:
67c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            return 0
68f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        for d in path.split(os.pathsep):
69f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            exe = os.path.join(d, cmd)
70f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            if os.path.isfile(exe):
71f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                return 1
72f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        return 0
73c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
74f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    class GenericBrowser:
75f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        def __init__(self, cmd):
76f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            self.command = cmd
77c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
78f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        def open(self, url, new=0):
79f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            os.system(self.command % url)
80c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
81f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        def open_new(self, url):	# Deprecated.  May be removed in 2.1.
82f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            self.open(url)
83c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
84f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    # Easy cases first -- register console browsers if we have them.
85f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    if os.environ.get("TERM"):
86f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        # The Links browser <http://artax.karlin.mff.cuni.cz/~mikulas/links/>
87f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        if _iscommand("links"):
88f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            register("links", None, GenericBrowser("links %s"))
89f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        # The Lynx browser <http://lynx.browser.org/>
90f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        if _iscommand("lynx"):
91f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            register("lynx", None, GenericBrowser("lynx %s"))
92f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        # The w3m browser <http://ei5nazha.yz.yamagata-u.ac.jp/~aito/w3m/eng/>
93f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        if _iscommand("w3m"):
94f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            register("w3m", None, GenericBrowser("w3m %s"))
95f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
96f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    # X browsers have mre in the way of options
97f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    if os.environ.get("DISPLAY"):
98f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        # First, the Netscape series
99f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        if _iscommand("netscape") or _iscommand("mozilla"):
100f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            class Netscape:
101f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                "Launcher class for Netscape browsers."
102f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                def __init__(self, name):
103f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    self.name = name
104f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
105f79cb2db3eae59f80e8031d45376dc5f48d2af04Eric S. Raymond                def _remote(self, action, autoraise):
106f79cb2db3eae59f80e8031d45376dc5f48d2af04Eric S. Raymond                    raise_opt = ("-noraise", "-raise")[autoraise]
107f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    cmd = "%s %s -remote '%s' >/dev/null 2>&1" % (self.name, raise_opt, action)
108f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    rc = os.system(cmd)
109f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    if rc:
110f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        import time
111f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        os.system("%s -no-about-splash &" % self.name)
112f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        time.sleep(PROCESS_CREATION_DELAY)
113f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        rc = os.system(cmd)
114f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    return not rc
115f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
116f79cb2db3eae59f80e8031d45376dc5f48d2af04Eric S. Raymond                def open(self, url, new=0, autoraise=1):
117f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    if new:
118f79cb2db3eae59f80e8031d45376dc5f48d2af04Eric S. Raymond                        self._remote("openURL(%s, new-window)"%url, autoraise)
119f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    else:
120f79cb2db3eae59f80e8031d45376dc5f48d2af04Eric S. Raymond                        self._remote("openURL(%s)" % url, autoraise)
121f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
122f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                # Deprecated.  May be removed in 2.1.
123f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                def open_new(self, url):
124f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    self.open(url, 1)
125f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
126f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            if _iscommand("mozilla"):
127f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                register("mozilla", None, Netscape("mozilla"))
128f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            if _iscommand("netscape"):
129f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                register("netscape", None, Netscape("netscape"))
130f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
131f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        # Next, Mosaic -- old but still in use.
132f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        if _iscommand("mosaic"):
133f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            register("mosaic", None, GenericBrowser("mosaic %s >/dev/null &"))
134f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
135f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        # Konqueror/kfm, the KDE browser.
136f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        if _iscommand("kfm"):
137f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            class Konqueror:
138f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                """Controller for the KDE File Manager (kfm, or Konqueror).
139f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
140f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                See http://developer.kde.org/documentation/other/kfmclient.html
141f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                for more information on the Konqueror remote-control interface.
142f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
143f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                """
144f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                def _remote(self, action):
145f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    cmd = "kfmclient %s >/dev/null 2>&1" % action
146f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    rc = os.system(cmd)
147f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    if rc:
148f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        import time
149f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        os.system("kfm -d &")
150f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        time.sleep(PROCESS_CREATION_DELAY)
151f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        rc = os.system(cmd)
152f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    return not rc
153f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
154f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                def open(self, url, new=1):
155f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    # XXX Currently I know no way to prevent KFM from opening a new win.
156f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    self._remote("openURL %s" % url)
157f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
158f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                # Deprecated.  May be removed in 2.1.
159f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                open_new = open
160f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
161f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            register("kfm", Konqueror, None)
162f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
163f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        # Grail, the Python browser.
164f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        if _iscommand("grail"):
165f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            class Grail:
166f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                # There should be a way to maintain a connection to
167f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                # Grail, but the Grail remote control protocol doesn't
168f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                # really allow that at this point.  It probably neverwill!
169f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                def _find_grail_rc(self):
170f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    import glob
171f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    import pwd
172f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    import socket
173f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    import tempfile
174f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    tempdir = os.path.join(tempfile.gettempdir(), ".grail-unix")
175f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    user = pwd.getpwuid(_os.getuid())[0]
176f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    filename = os.path.join(tempdir, user + "-*")
177f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    maybes = glob.glob(filename)
178f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    if not maybes:
179f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        return None
180f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
181f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    for fn in maybes:
182f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        # need to PING each one until we find one that's live
183f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        try:
184f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                            s.connect(fn)
185f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        except socket.error:
186f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                            # no good; attempt to clean it out, but don't fail:
187f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                            try:
188f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                                os.unlink(fn)
189f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                            except IOError:
190f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                                pass
191f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        else:
192f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                            return s
193f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
194f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                def _remote(self, action):
195f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    s = self._find_grail_rc()
196f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    if not s:
197f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        return 0
198f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    s.send(action)
199f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    s.close()
200f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    return 1
201f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
202f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                def open(self, url, new=0):
203f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    if new:
204f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        self._remote("LOADNEW " + url)
205f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    else:
206f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                        self._remote("LOAD " + url)
207f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
208f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                # Deprecated.  May be removed in 2.1.
209f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                def open_new(self, url):
210f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                    self.open(url, 1)
211f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
212f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            register("grail", Grail, None)
213c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
214f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond#
215f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# Platform support for Windows
216f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond#
217c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
218f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymondif sys.platform[:3] == "win":
219f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    global _tryorder
220f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    _tryorder = ("netscape", "windows-default")
221c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
222f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    class WindowsDefault:
223f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        def open(self, url, new=0):
224f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            os.startfile(url)
225c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
226f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        def open_new(self, url):        # Deprecated.  May be removed in 2.1.
227f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond            self.open(url)
228c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
229c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    register("windows-default", WindowsDefault)
230c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
231c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake#
232f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# Platform support for MacOS
233f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond#
234c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
235c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Draketry:
236c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    import ic
237c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeexcept ImportError:
238c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    pass
239c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeelse:
240c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    class InternetConfig:
241c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        def open(self, url, new=0):
2422595a837b5b536bd850660e8337a96116eccf80aGuido van Rossum            ic.launchurl(url)
243c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
244f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond        def open_new(self, url):        # Deprecated.  May be removed in 2.1.
245c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            self.open(url)
246c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
247f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    # internet-config is the only supported controller on MacOS,
248f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    # so don't mess with the default!
249f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    _tryorder = ("internet-config")
250c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    register("internet-config", InternetConfig)
251f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
252f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# OK, now that we know what the default preference orders for each
253f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# platform are, allow user to override them with the BROWSER variable.
254f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond#
255f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymondif os.environ.has_key("BROWSER"):
256f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    # It's the user's responsibility to register handlers for any unknown
257f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    # browser referenced by this value, before calling open().
258f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    _tryorder = os.environ["BROWSER"].split(":")
259f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymondelse:
260f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    # Optimization: filter out alternatives that aren't available, so we can
261f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    # avoid has_key() tests at runtime.  (This may also allow some unused
262f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    # classes and class-instance storage to be garbage-collected.)
263f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond    _tryorder = filter(lambda x: _browsers.has_key(x.lower()) or x.find("%s")>-1,\
264f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond                       _tryorder)
265f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond
266f7f185116a8274b105edc1be64ffc9c8061c7f43Eric S. Raymond# end
267