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