webbrowser.py revision c70b4483d2c5042c68198dc7c4945ef3cfc95b27
1c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake"""Remote-control interfaces to some browsers."""
2c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
3c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeimport os
4c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeimport sys
5c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
6c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
7c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred DrakePROCESS_CREATION_DELAY = 4
8c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
9c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
10c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeclass Error(Exception):
11c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    pass
12c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
13c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
14c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake_browsers = {}
15c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
16c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakedef register(name, klass, instance=None):
17c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    """Register a browser connector and, optionally, connection."""
18c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    _browsers[name.lower()] = [klass, instance]
19c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
20c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
21c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakedef get(name=None):
22c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    """Retrieve a connection to a browser by type name, or the default
23c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    browser."""
24c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    name = name or DEFAULT_BROWSER
25c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    try:
26c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        L = _browsers[name.lower()]
27c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    except KeyError:
28c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        raise ValueError, "unknown browser type: " + `name`
29c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    if L[1] is None:
30c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        L[1] = L[0]()
31c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    return L[1]
32c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
33c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
34c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake# Please note: the following definition hides a builtin function.
35c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
36c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakedef open(url, new=0):
37c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    get().open(url, new)
38c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
39c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
40c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakedef open_new(url):
41c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    get().open_new(url)
42c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
43c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
44c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakedef _iscommand(cmd):
45c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    """Return true if cmd can be found on the executable search path."""
46c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    path = os.environ.get("PATH")
47c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    if not path:
48c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        return 0
49c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    for d in path.split(os.pathsep):
50c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        exe = os.path.join(d, cmd)
51c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        if os.path.isfile(exe):
52c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            return 1
53c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    return 0
54c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
55c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
56c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeclass CommandLineBrowser:
57c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    _browsers = []
58c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    if os.environ.get("DISPLAY"):
59c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        _browsers.extend([
60c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            ("netscape", "netscape %s >/dev/null &"),
61c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            ("mosaic", "mosaic %s >/dev/null &"),
62c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            ])
63c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    _browsers.extend([
64c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        ("lynx", "lynx %s"),
65c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        ("w3m", "w3m %s"),
66c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        ])
67c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
68c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def open(self, url, new=0):
69c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        for exe, cmd in self._browsers:
70c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            if _iscommand(exe):
71c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake                os.system(cmd % url)
72c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake                return
73c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        raise Error("could not locate runnable browser")
74c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
75c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def open_new(self, url):
76c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        self.open(url)
77c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
78c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeregister("command-line", CommandLineBrowser)
79c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
80c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
81c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeclass Netscape:
82c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    autoRaise = 1
83c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
84c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def _remote(self, action):
85c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        raise_opt = ("-noraise", "-raise")[self.autoRaise]
86c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        cmd = "netscape %s -remote '%s' >/dev/null 2>&1" % (raise_opt, action)
87c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        rc = os.system(cmd)
88c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        if rc:
89c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            import time
90c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            os.system("netscape -no-about-splash &")
91c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            time.sleep(PROCESS_CREATION_DELAY)
92c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            rc = os.system(cmd)
93c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        return not rc
94c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
95c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def open(self, url, new=0):
96c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        if new:
97c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            self.open_new(url)
98c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        else:
99c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            self._remote("openURL(%s)" % url)
100c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
101c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def open_new(self, url):
102c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        self._remote("openURL(%s, new-window)" % url)
103c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
104c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeregister("netscape", Netscape)
105c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
106c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
107c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeclass Konquerer:
108c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    """Controller for the KDE File Manager (kfm, or Konquerer).
109c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
110c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    See http://developer.kde.org/documentation/other/kfmclient.html
111c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    for more information on the Konquerer remote-control interface.
112c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
113c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    """
114c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def _remote(self, action):
115c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        cmd = "kfmclient %s >/dev/null 2>&1" % action
116c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        rc = os.system(cmd)
117c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        if rc:
118c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            import time
119c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            os.system("kfm -d &")
120c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            time.sleep(PROCESS_CREATION_DELAY)
121c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            rc = os.system(cmd)
122c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        return not rc
123c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
124c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def open(self, url, new=1):
125c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake	# XXX currently I know no way to prevent KFM from opening a new win.
126c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        self.open_new(url)
127c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
128c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def open_new(self, url):
129c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        self._remote("openURL %s" % url)
130c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
131c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeregister("kfm", Konquerer)
132c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
133c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
134c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeclass Grail:
135c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    # There should be a way to maintain a connection to Grail, but the
136c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    # Grail remote control protocol doesn't really allow that at this
137c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    # point.  It probably never will!
138c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
139c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def _find_grail_rc(self):
140c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        import glob
141c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        import pwd
142c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        import socket
143c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        import tempfile
144c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        tempdir = os.path.join(tempfile.gettempdir(), ".grail-unix")
145c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        user = pwd.getpwuid(_os.getuid())[0]
146c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        filename = os.path.join(tempdir, user + "-*")
147c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        maybes = glob.glob(filename)
148c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        if not maybes:
149c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            return None
150c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
151c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        for fn in maybes:
152c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            # need to PING each one until we find one that's live
153c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            try:
154c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake                s.connect(fn)
155c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            except socket.error:
156c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake                # no good; attempt to clean it out, but don't fail:
157c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake                try:
158c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake                    os.unlink(fn)
159c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake                except IOError:
160c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake                    pass
161c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            else:
162c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake                return s
163c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
164c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def _remote(self, action):
165c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        s = self._find_grail_rc()
166c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        if not s:
167c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            return 0
168c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        s.send(action)
169c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        s.close()
170c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        return 1
171c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
172c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def open(self, url, new=0):
173c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        if new:
174c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            self.open_new(url)
175c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        else:
176c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            self._remote("LOAD " + url)
177c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
178c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def open_new(self, url):
179c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        self._remote("LOADNEW " + url)
180c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
181c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeregister("grail", Grail)
182c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
183c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
184c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeclass WindowsDefault:
185c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def open(self, url, new=0):
186c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        import win32api, win32con
187c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        win32api.ShellExecute(0, "open", url, None, ".",
188c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake                              win32con.SW_SHOWNORMAL)
189c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
190c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    def open_new(self, url):
191c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        self.open(url)
192c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
193c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
194c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred DrakeDEFAULT_BROWSER = "command-line"
195c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
196c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeif sys.platform[:3] == "win":
197c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    del _browsers["kfm"]
198c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    register("windows-default", WindowsDefault)
199c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    DEFAULT_BROWSER = "windows-default"
200c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeelif os.environ.get("DISPLAY"):
201c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    if os.environ.get("KDEDIR"):
202c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        DEFAULT_BROWSER = "kfm"
203c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    elif _iscommand("netscape"):
204c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        DEFAULT_BROWSER = "netscape"
205c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
206c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake# If the $BROWSER environment variable is set and true, let that be
207c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake# the name of the browser to use:
208c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake#
209c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred DrakeDEFAULT_BROWSER = os.environ.get("BROWSER") or DEFAULT_BROWSER
210c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
211c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
212c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake# Now try to support the MacOS world.  This is the only supported
213c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake# controller on that platform, so don't mess with the default!
214c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
215c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Draketry:
216c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    import ic
217c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeexcept ImportError:
218c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    pass
219c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drakeelse:
220c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    class InternetConfig:
221c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        def open(self, url, new=0):
222c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            ic.launcurl(url)
223c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
224c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake        def open_new(self, url):
225c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake            self.open(url)
226c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake
227c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    _browsers.clear()
228c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    register("internet-config", InternetConfig)
229c70b4483d2c5042c68198dc7c4945ef3cfc95b27Fred Drake    DEFAULT_BROWSER = "internet-config"
230