summaryrefslogtreecommitdiffstats
path: root/Lib/webbrowser.py
blob: 759f470dc4d33ebe2e53679fe20cd7d248dc4380 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
"""Remote-control interfaces to some browsers."""

import os
import sys


PROCESS_CREATION_DELAY = 4


class Error(Exception):
    pass


_browsers = {}

def register(name, klass, instance=None):
    """Register a browser connector and, optionally, connection."""
    _browsers[name.lower()] = [klass, instance]


def get(name=None):
    """Retrieve a connection to a browser by type name, or the default
    browser."""
    name = name or DEFAULT_BROWSER
    try:
        L = _browsers[name.lower()]
    except KeyError:
        raise ValueError, "unknown browser type: " + `name`
    if L[1] is None:
        L[1] = L[0]()
    return L[1]


# Please note: the following definition hides a builtin function.

def open(url, new=0):
    get().open(url, new)


def open_new(url):
    get().open_new(url)


def _iscommand(cmd):
    """Return true if cmd can be found on the executable search path."""
    path = os.environ.get("PATH")
    if not path:
        return 0
    for d in path.split(os.pathsep):
        exe = os.path.join(d, cmd)
        if os.path.isfile(exe):
            return 1
    return 0


class CommandLineBrowser:
    _browsers = []
    if os.environ.get("DISPLAY"):
        _browsers.extend([
            ("netscape", "netscape %s >/dev/null &"),
            ("mosaic", "mosaic %s >/dev/null &"),
            ])
    _browsers.extend([
        ("lynx", "lynx %s"),
        ("w3m", "w3m %s"),
        ])

    def open(self, url, new=0):
        for exe, cmd in self._browsers:
            if _iscommand(exe):
                os.system(cmd % url)
                return
        raise Error("could not locate runnable browser")

    def open_new(self, url):
        self.open(url)

register("command-line", CommandLineBrowser)


class Netscape:
    autoRaise = 1

    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 Konqueror:
    """Controller for the KDE File Manager (kfm, or Konqueror).

    See http://developer.kde.org/documentation/other/kfmclient.html
    for more information on the Konqueror remote-control interface.

    """
    def _remote(self, action):
        cmd = "kfmclient %s >/dev/null 2>&1" % action
        rc = os.system(cmd)
        if rc:
            import time
            os.system("kfm -d &")
            time.sleep(PROCESS_CREATION_DELAY)
            rc = os.system(cmd)
        return not rc

    def open(self, url, new=1):
	# XXX currently I know no way to prevent KFM from opening a new win.
        self.open_new(url)

    def open_new(self, url):
        self._remote("openURL %s" % url)

register("kfm", Konqueror)


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):
        os.startfile(url)

    def open_new(self, url):
        self.open(url)


DEFAULT_BROWSER = "command-line"

if sys.platform[:3] == "win":
    del _browsers["kfm"]
    register("windows-default", WindowsDefault)
    DEFAULT_BROWSER = "windows-default"
elif os.environ.get("DISPLAY"):
    if _iscommand("netscape"):
        DEFAULT_BROWSER = "netscape"

# If the $BROWSER environment variable is set and true, let that be
# the name of the browser to use:
#
DEFAULT_BROWSER = os.environ.get("BROWSER") or DEFAULT_BROWSER


# Now try to support the MacOS world.  This is the only supported
# controller on that platform, so don't mess with the default!

try:
    import ic
except ImportError:
    pass
else:
    class InternetConfig:
        def open(self, url, new=0):
            ic.launchurl(url)

        def open_new(self, url):
            self.open(url)

    _browsers.clear()
    register("internet-config", InternetConfig)
    DEFAULT_BROWSER = "internet-config"