blob: 1db52d0faff1b5908c04e2fd0ac6f6d690d76160 [file] [log] [blame]
Georg Brandle8f24432005-10-03 14:16:44 +00001#! /usr/bin/env python
Ka-Ping Yee0a8c29b2001-03-02 02:01:40 +00002"""Interfaces for launching and remotely controlling Web browsers."""
Fred Drakec70b4482000-07-09 16:45:56 +00003
4import os
5import sys
Georg Brandle8f24432005-10-03 14:16:44 +00006import stat
Fred Drakec70b4482000-07-09 16:45:56 +00007
Georg Brandle8f24432005-10-03 14:16:44 +00008__all__ = ["Error", "open", "open_new", "open_new_tab", "get", "register"]
Skip Montanaro40fc1602001-03-01 04:27:19 +00009
Fred Drakec70b4482000-07-09 16:45:56 +000010class Error(Exception):
11 pass
12
Tim Peters658cba62001-02-09 20:06:00 +000013_browsers = {} # Dictionary of available browser controllers
14_tryorder = [] # Preference order of available browsers
Fred Drakec70b4482000-07-09 16:45:56 +000015
Georg Brandle8f24432005-10-03 14:16:44 +000016def register(name, klass, instance=None, update_tryorder=1):
Fred Drakec70b4482000-07-09 16:45:56 +000017 """Register a browser connector and, optionally, connection."""
18 _browsers[name.lower()] = [klass, instance]
Georg Brandle8f24432005-10-03 14:16:44 +000019 if update_tryorder > 0:
20 _tryorder.append(name)
21 elif update_tryorder < 0:
22 _tryorder.insert(0, name)
Fred Drakec70b4482000-07-09 16:45:56 +000023
Eric S. Raymondf7f18512001-01-23 13:16:32 +000024def get(using=None):
25 """Return a browser launcher instance appropriate for the environment."""
Raymond Hettinger10ff7062002-06-02 03:04:52 +000026 if using is not None:
Eric S. Raymondf7f18512001-01-23 13:16:32 +000027 alternatives = [using]
28 else:
29 alternatives = _tryorder
30 for browser in alternatives:
Raymond Hettingerbac788a2004-05-04 09:21:43 +000031 if '%s' in browser:
Eric S. Raymondf7f18512001-01-23 13:16:32 +000032 # User gave us a command line, don't mess with it.
Eric S. Raymondf7eb4fa2001-03-31 01:50:52 +000033 return GenericBrowser(browser)
Eric S. Raymondf7f18512001-01-23 13:16:32 +000034 else:
Georg Brandle8f24432005-10-03 14:16:44 +000035 # User gave us a browser name or path.
Fred Drakef4e5bd92001-04-12 22:07:27 +000036 try:
37 command = _browsers[browser.lower()]
38 except KeyError:
39 command = _synthesize(browser)
Georg Brandle8f24432005-10-03 14:16:44 +000040 if command[1] is not None:
Eric S. Raymondf7f18512001-01-23 13:16:32 +000041 return command[1]
Georg Brandle8f24432005-10-03 14:16:44 +000042 elif command[0] is not None:
43 return command[0]()
Eric S. Raymondf7f18512001-01-23 13:16:32 +000044 raise Error("could not locate runnable browser")
Fred Drakec70b4482000-07-09 16:45:56 +000045
46# Please note: the following definition hides a builtin function.
Georg Brandle8f24432005-10-03 14:16:44 +000047# It is recommended one does "import webbrowser" and uses webbrowser.open(url)
48# instead of "from webbrowser import *".
Fred Drakec70b4482000-07-09 16:45:56 +000049
Eric S. Raymondf79cb2d2001-01-23 13:49:44 +000050def open(url, new=0, autoraise=1):
Georg Brandle8f24432005-10-03 14:16:44 +000051 for name in _tryorder:
52 browser = get(name)
53 if browser.open(url, new, autoraise):
54 return True
55 return False
Fred Drakec70b4482000-07-09 16:45:56 +000056
Fred Drake3f8f1642001-07-19 03:46:26 +000057def open_new(url):
Georg Brandle8f24432005-10-03 14:16:44 +000058 return open(url, 1)
59
60def open_new_tab(url):
61 return open(url, 2)
Fred Drakec70b4482000-07-09 16:45:56 +000062
Fred Drakef4e5bd92001-04-12 22:07:27 +000063
Georg Brandle8f24432005-10-03 14:16:44 +000064def _synthesize(browser, update_tryorder=1):
Fred Drakef4e5bd92001-04-12 22:07:27 +000065 """Attempt to synthesize a controller base on existing controllers.
66
67 This is useful to create a controller when a user specifies a path to
68 an entry in the BROWSER environment variable -- we can copy a general
69 controller to operate using a specific installation of the desired
70 browser in this way.
71
72 If we can't create a controller in this way, or if there is no
73 executable for the requested browser, return [None, None].
74
75 """
Georg Brandle8f24432005-10-03 14:16:44 +000076 cmd = browser.split()[0]
77 if not _iscommand(cmd):
Fred Drakef4e5bd92001-04-12 22:07:27 +000078 return [None, None]
Georg Brandle8f24432005-10-03 14:16:44 +000079 name = os.path.basename(cmd)
Fred Drakef4e5bd92001-04-12 22:07:27 +000080 try:
81 command = _browsers[name.lower()]
82 except KeyError:
83 return [None, None]
84 # now attempt to clone to fit the new name:
85 controller = command[1]
86 if controller and name.lower() == controller.basename:
87 import copy
88 controller = copy.copy(controller)
89 controller.name = browser
90 controller.basename = os.path.basename(browser)
Georg Brandle8f24432005-10-03 14:16:44 +000091 register(browser, None, controller, update_tryorder)
Fred Drakef4e5bd92001-04-12 22:07:27 +000092 return [None, controller]
Andrew M. Kuchling118aa532001-08-13 14:37:23 +000093 return [None, None]
Fred Drakef4e5bd92001-04-12 22:07:27 +000094
Fred Drake3f8f1642001-07-19 03:46:26 +000095
Georg Brandle8f24432005-10-03 14:16:44 +000096if sys.platform[:3] == "win":
97 def _isexecutable(cmd):
98 cmd = cmd.lower()
99 if os.path.isfile(cmd) and (cmd.endswith(".exe") or
100 cmd.endswith(".bat")):
101 return True
102 for ext in ".exe", ".bat":
103 if os.path.isfile(cmd + ext):
104 return True
105 return False
106else:
107 def _isexecutable(cmd):
108 if os.path.isfile(cmd):
109 mode = os.stat(cmd)[stat.ST_MODE]
110 if mode & stat.S_IXUSR or mode & stat.S_IXGRP or mode & stat.S_IXOTH:
111 return True
112 return False
113
Fred Drake3f8f1642001-07-19 03:46:26 +0000114def _iscommand(cmd):
Georg Brandle8f24432005-10-03 14:16:44 +0000115 """Return True if cmd is executable or can be found on the executable
116 search path."""
117 if _isexecutable(cmd):
118 return True
Fred Drake3f8f1642001-07-19 03:46:26 +0000119 path = os.environ.get("PATH")
120 if not path:
Tim Petersbc0e9102002-04-04 22:55:58 +0000121 return False
Fred Drake3f8f1642001-07-19 03:46:26 +0000122 for d in path.split(os.pathsep):
123 exe = os.path.join(d, cmd)
Georg Brandle8f24432005-10-03 14:16:44 +0000124 if _isexecutable(exe):
Tim Petersbc0e9102002-04-04 22:55:58 +0000125 return True
126 return False
Fred Drake3f8f1642001-07-19 03:46:26 +0000127
128
Georg Brandle8f24432005-10-03 14:16:44 +0000129# General parent classes
130
131class BaseBrowser(object):
132 """Parent class for all browsers."""
133
134 def __init__(self, name=""):
135 self.name = name
Georg Brandlb9801132005-10-08 20:47:38 +0000136 self.basename = name
Georg Brandle8f24432005-10-03 14:16:44 +0000137
Neal Norwitz196f7332005-10-04 03:17:49 +0000138 def open(self, url, new=0, autoraise=1):
139 raise NotImplementedError
140
Georg Brandle8f24432005-10-03 14:16:44 +0000141 def open_new(self, url):
142 return self.open(url, 1)
143
144 def open_new_tab(self, url):
145 return self.open(url, 2)
Fred Drake3f8f1642001-07-19 03:46:26 +0000146
147
Georg Brandle8f24432005-10-03 14:16:44 +0000148class GenericBrowser(BaseBrowser):
149 """Class for all browsers started with a command
150 and without remote functionality."""
151
Fred Drake3f8f1642001-07-19 03:46:26 +0000152 def __init__(self, cmd):
153 self.name, self.args = cmd.split(None, 1)
Georg Brandlb9801132005-10-08 20:47:38 +0000154 self.basename = os.path.basename(self.name)
Fred Drake3f8f1642001-07-19 03:46:26 +0000155
156 def open(self, url, new=0, autoraise=1):
Fred Drake925f1442002-01-07 15:29:01 +0000157 assert "'" not in url
Fred Drake3f8f1642001-07-19 03:46:26 +0000158 command = "%s %s" % (self.name, self.args)
Georg Brandle8f24432005-10-03 14:16:44 +0000159 rc = os.system(command % url)
160 return not rc
Fred Drake3f8f1642001-07-19 03:46:26 +0000161
162
Georg Brandle8f24432005-10-03 14:16:44 +0000163class UnixBrowser(BaseBrowser):
164 """Parent class for all Unix browsers with remote functionality."""
Fred Drake3f8f1642001-07-19 03:46:26 +0000165
Georg Brandle8f24432005-10-03 14:16:44 +0000166 raise_opts = None
167
168 remote_cmd = ''
169 remote_action = None
170 remote_action_newwin = None
171 remote_action_newtab = None
172 remote_background = False
173
174 def _remote(self, url, action, autoraise):
175 autoraise = int(bool(autoraise)) # always 0/1
176 raise_opt = self.raise_opts and self.raise_opts[autoraise] or ''
177 cmd = "%s %s %s '%s' >/dev/null 2>&1" % (self.name, raise_opt,
178 self.remote_cmd, action)
Neal Norwitz196f7332005-10-04 03:17:49 +0000179 if self.remote_background:
Georg Brandle8f24432005-10-03 14:16:44 +0000180 cmd += ' &'
Fred Drake3f8f1642001-07-19 03:46:26 +0000181 rc = os.system(cmd)
182 if rc:
Georg Brandle8f24432005-10-03 14:16:44 +0000183 # bad return status, try again with simpler command
184 rc = os.system("%s %s" % (self.name, url))
Fred Drake3f8f1642001-07-19 03:46:26 +0000185 return not rc
186
187 def open(self, url, new=0, autoraise=1):
Georg Brandle8f24432005-10-03 14:16:44 +0000188 assert "'" not in url
189 if new == 0:
190 action = self.remote_action
191 elif new == 1:
192 action = self.remote_action_newwin
193 elif new == 2:
194 if self.remote_action_newtab is None:
195 action = self.remote_action_newwin
196 else:
197 action = self.remote_action_newtab
Fred Drake3f8f1642001-07-19 03:46:26 +0000198 else:
Georg Brandle8f24432005-10-03 14:16:44 +0000199 raise Error("Bad 'new' parameter to open(); expected 0, 1, or 2, got %s" % new)
200 return self._remote(url, action % url, autoraise)
Fred Drake3f8f1642001-07-19 03:46:26 +0000201
202
Georg Brandle8f24432005-10-03 14:16:44 +0000203class Mozilla(UnixBrowser):
204 """Launcher class for Mozilla/Netscape browsers."""
Neal Norwitz8dd28eb2002-10-10 22:49:29 +0000205
Georg Brandle8f24432005-10-03 14:16:44 +0000206 raise_opts = ("-noraise", "-raise")
Neal Norwitz8dd28eb2002-10-10 22:49:29 +0000207
Georg Brandle8f24432005-10-03 14:16:44 +0000208 remote_cmd = '-remote'
209 remote_action = "openURL(%s)"
210 remote_action_newwin = "openURL(%s,new-window)"
211 remote_action_newtab = "openURL(%s,new-tab)"
Neal Norwitz8dd28eb2002-10-10 22:49:29 +0000212
Georg Brandle8f24432005-10-03 14:16:44 +0000213Netscape = Mozilla
Neal Norwitz8dd28eb2002-10-10 22:49:29 +0000214
215
Georg Brandle8f24432005-10-03 14:16:44 +0000216class Galeon(UnixBrowser):
217 """Launcher class for Galeon/Epiphany browsers."""
218
219 raise_opts = ("-noraise", "")
220 remote_action = "-n '%s'"
221 remote_action_newwin = "-w '%s'"
222
223 remote_background = True
224
225
226class Konqueror(BaseBrowser):
Fred Drake3f8f1642001-07-19 03:46:26 +0000227 """Controller for the KDE File Manager (kfm, or Konqueror).
228
229 See http://developer.kde.org/documentation/other/kfmclient.html
230 for more information on the Konqueror remote-control interface.
231
232 """
Fred Drake3f8f1642001-07-19 03:46:26 +0000233
Georg Brandle8f24432005-10-03 14:16:44 +0000234 def _remote(self, url, action):
235 # kfmclient is the new KDE way of opening URLs.
Neal Norwitz520cdf72002-10-11 22:04:22 +0000236 cmd = "kfmclient %s >/dev/null 2>&1" % action
Fred Drake3f8f1642001-07-19 03:46:26 +0000237 rc = os.system(cmd)
Georg Brandle8f24432005-10-03 14:16:44 +0000238 # Fall back to other variants.
Fred Drake3f8f1642001-07-19 03:46:26 +0000239 if rc:
Georg Brandle8f24432005-10-03 14:16:44 +0000240 if _iscommand("konqueror"):
241 rc = os.system(self.name + " --silent '%s' &" % url)
242 elif _iscommand("kfm"):
243 rc = os.system(self.name + " -d '%s'" % url)
Fred Drake3f8f1642001-07-19 03:46:26 +0000244 return not rc
245
Georg Brandle8f24432005-10-03 14:16:44 +0000246 def open(self, url, new=0, autoraise=1):
Fred Drake3f8f1642001-07-19 03:46:26 +0000247 # XXX Currently I know no way to prevent KFM from
248 # opening a new win.
Neal Norwitz520cdf72002-10-11 22:04:22 +0000249 assert "'" not in url
Georg Brandle8f24432005-10-03 14:16:44 +0000250 if new == 2:
251 action = "newTab '%s'" % url
252 else:
253 action = "openURL '%s'" % url
254 ok = self._remote(url, action)
255 return ok
Fred Drake3f8f1642001-07-19 03:46:26 +0000256
257
Georg Brandle8f24432005-10-03 14:16:44 +0000258class Opera(UnixBrowser):
259 "Launcher class for Opera browser."
260
261 raise_opts = ("", "-raise")
262
263 remote_cmd = '-remote'
264 remote_action = "openURL(%s)"
265 remote_action_newwin = "openURL(%s,new-window)"
266 remote_action_newtab = "openURL(%s,new-page)"
267
268
269class Elinks(UnixBrowser):
270 "Launcher class for Elinks browsers."
271
272 remote_cmd = '-remote'
273 remote_action = "openURL(%s)"
274 remote_action_newwin = "openURL(%s,new-window)"
275 remote_action_newtab = "openURL(%s,new-tab)"
276
277 def _remote(self, url, action, autoraise):
278 # elinks doesn't like its stdout to be redirected -
279 # it uses redirected stdout as a signal to do -dump
280 cmd = "%s %s '%s' 2>/dev/null" % (self.name,
281 self.remote_cmd, action)
282 rc = os.system(cmd)
283 if rc:
284 rc = os.system("%s %s" % (self.name, url))
285 return not rc
286
287
288class Grail(BaseBrowser):
Fred Drake3f8f1642001-07-19 03:46:26 +0000289 # There should be a way to maintain a connection to Grail, but the
290 # Grail remote control protocol doesn't really allow that at this
291 # point. It probably neverwill!
292 def _find_grail_rc(self):
293 import glob
294 import pwd
295 import socket
296 import tempfile
297 tempdir = os.path.join(tempfile.gettempdir(),
298 ".grail-unix")
Fred Drake16623fe2001-10-13 16:00:52 +0000299 user = pwd.getpwuid(os.getuid())[0]
Fred Drake3f8f1642001-07-19 03:46:26 +0000300 filename = os.path.join(tempdir, user + "-*")
301 maybes = glob.glob(filename)
302 if not maybes:
303 return None
304 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
305 for fn in maybes:
306 # need to PING each one until we find one that's live
307 try:
308 s.connect(fn)
309 except socket.error:
310 # no good; attempt to clean it out, but don't fail:
311 try:
312 os.unlink(fn)
313 except IOError:
314 pass
315 else:
316 return s
317
318 def _remote(self, action):
319 s = self._find_grail_rc()
320 if not s:
321 return 0
322 s.send(action)
323 s.close()
324 return 1
325
326 def open(self, url, new=0, autoraise=1):
327 if new:
Georg Brandle8f24432005-10-03 14:16:44 +0000328 ok = self._remote("LOADNEW " + url)
Fred Drake3f8f1642001-07-19 03:46:26 +0000329 else:
Georg Brandle8f24432005-10-03 14:16:44 +0000330 ok = self._remote("LOAD " + url)
331 return ok
Fred Drake3f8f1642001-07-19 03:46:26 +0000332
Fred Drakec70b4482000-07-09 16:45:56 +0000333
Tim Peters658cba62001-02-09 20:06:00 +0000334#
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000335# Platform support for Unix
336#
Fred Drakec70b4482000-07-09 16:45:56 +0000337
Georg Brandle8f24432005-10-03 14:16:44 +0000338# These are the right tests because all these Unix browsers require either
339# a console terminal or an X display to run.
Fred Drakec70b4482000-07-09 16:45:56 +0000340
Neal Norwitz196f7332005-10-04 03:17:49 +0000341def register_X_browsers():
Georg Brandle8f24432005-10-03 14:16:44 +0000342 # First, the Mozilla/Netscape browsers
343 for browser in ("mozilla-firefox", "firefox",
344 "mozilla-firebird", "firebird",
345 "mozilla", "netscape"):
346 if _iscommand(browser):
347 register(browser, None, Mozilla(browser))
Gustavo Niemeyer1456fde2002-11-25 17:25:04 +0000348
Georg Brandle8f24432005-10-03 14:16:44 +0000349 # The default Gnome browser
350 if _iscommand("gconftool-2"):
351 # get the web browser string from gconftool
352 gc = 'gconftool-2 -g /desktop/gnome/url-handlers/http/command'
353 out = os.popen(gc)
354 commd = out.read().strip()
355 retncode = out.close()
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000356
Georg Brandle8f24432005-10-03 14:16:44 +0000357 # if successful, register it
358 if retncode == None and len(commd) != 0:
359 register("gnome", None, GenericBrowser(
360 commd + " '%s' >/dev/null &"))
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000361
Georg Brandle8f24432005-10-03 14:16:44 +0000362 # Konqueror/kfm, the KDE browser.
Georg Brandlb9801132005-10-08 20:47:38 +0000363 if _iscommand("kfm"):
364 register("kfm", Konqueror, Konqueror("kfm"))
365 elif _iscommand("konqueror"):
366 register("konqueror", Konqueror, Konqueror("konqueror"))
Neal Norwitz8dd28eb2002-10-10 22:49:29 +0000367
Georg Brandle8f24432005-10-03 14:16:44 +0000368 # Gnome's Galeon and Epiphany
369 for browser in ("galeon", "epiphany"):
370 if _iscommand(browser):
371 register(browser, None, Galeon(browser))
Gustavo Niemeyer1456fde2002-11-25 17:25:04 +0000372
Georg Brandle8f24432005-10-03 14:16:44 +0000373 # Skipstone, another Gtk/Mozilla based browser
374 if _iscommand("skipstone"):
375 register("skipstone", None, GenericBrowser("skipstone '%s' &"))
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000376
Georg Brandle8f24432005-10-03 14:16:44 +0000377 # Opera, quite popular
378 if _iscommand("opera"):
379 register("opera", None, Opera("opera"))
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000380
Georg Brandle8f24432005-10-03 14:16:44 +0000381 # Next, Mosaic -- old but still in use.
382 if _iscommand("mosaic"):
383 register("mosaic", None, GenericBrowser("mosaic '%s' &"))
Fred Drake3f8f1642001-07-19 03:46:26 +0000384
Georg Brandle8f24432005-10-03 14:16:44 +0000385 # Grail, the Python browser. Does anybody still use it?
386 if _iscommand("grail"):
387 register("grail", Grail, None)
Fred Drake3f8f1642001-07-19 03:46:26 +0000388
Neal Norwitz196f7332005-10-04 03:17:49 +0000389# Prefer X browsers if present
390if os.environ.get("DISPLAY"):
391 register_X_browsers()
392
Georg Brandle8f24432005-10-03 14:16:44 +0000393# Also try console browsers
394if os.environ.get("TERM"):
395 # The Links/elinks browsers <http://artax.karlin.mff.cuni.cz/~mikulas/links/>
396 if _iscommand("links"):
397 register("links", None, GenericBrowser("links '%s'"))
398 if _iscommand("elinks"):
399 register("elinks", None, Elinks("elinks"))
400 # The Lynx browser <http://lynx.isc.org/>, <http://lynx.browser.org/>
401 if _iscommand("lynx"):
402 register("lynx", None, GenericBrowser("lynx '%s'"))
403 # The w3m browser <http://w3m.sourceforge.net/>
404 if _iscommand("w3m"):
405 register("w3m", None, GenericBrowser("w3m '%s'"))
Fred Drake3f8f1642001-07-19 03:46:26 +0000406
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000407#
408# Platform support for Windows
409#
Fred Drakec70b4482000-07-09 16:45:56 +0000410
411if sys.platform[:3] == "win":
Georg Brandle8f24432005-10-03 14:16:44 +0000412 class WindowsDefault(BaseBrowser):
413 def open(self, url, new=0, autoraise=1):
414 os.startfile(url)
415 return True # Oh, my...
416
417 _tryorder = []
418 _browsers = {}
419 # Prefer mozilla/netscape/opera if present
420 for browser in ("firefox", "firebird", "mozilla", "netscape", "opera"):
421 if _iscommand(browser):
422 register(browser, None, GenericBrowser(browser + ' %s'))
Fred Drakec70b4482000-07-09 16:45:56 +0000423 register("windows-default", WindowsDefault)
Fred Drakec70b4482000-07-09 16:45:56 +0000424
Fred Drakec70b4482000-07-09 16:45:56 +0000425#
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000426# Platform support for MacOS
427#
Fred Drakec70b4482000-07-09 16:45:56 +0000428
429try:
430 import ic
431except ImportError:
432 pass
433else:
Georg Brandle8f24432005-10-03 14:16:44 +0000434 class InternetConfig(BaseBrowser):
435 def open(self, url, new=0, autoraise=1):
436 ic.launchurl(url)
437 return True # Any way to get status?
438
439 register("internet-config", InternetConfig, update_tryorder=-1)
440
441if sys.platform == 'darwin':
442 # Adapted from patch submitted to SourceForge by Steven J. Burr
443 class MacOSX(BaseBrowser):
444 """Launcher class for Aqua browsers on Mac OS X
445
446 Optionally specify a browser name on instantiation. Note that this
447 will not work for Aqua browsers if the user has moved the application
448 package after installation.
449
450 If no browser is specified, the default browser, as specified in the
451 Internet System Preferences panel, will be used.
452 """
453 def __init__(self, name):
454 self.name = name
455
456 def open(self, url, new=0, autoraise=1):
457 assert "'" not in url
458 # new must be 0 or 1
459 new = int(bool(new))
460 if self.name == "default":
461 # User called open, open_new or get without a browser parameter
462 script = _safequote('open location "%s"', url) # opens in default browser
463 else:
464 # User called get and chose a browser
465 if self.name == "OmniWeb":
466 toWindow = ""
467 else:
468 # Include toWindow parameter of OpenURL command for browsers
469 # that support it. 0 == new window; -1 == existing
470 toWindow = "toWindow %d" % (new - 1)
471 cmd = _safequote('OpenURL "%s"', url)
472 script = '''tell application "%s"
473 activate
474 %s %s
475 end tell''' % (self.name, cmd, toWindow)
476 # Open pipe to AppleScript through osascript command
477 osapipe = os.popen("osascript", "w")
478 if osapipe is None:
479 return False
480 # Write script to osascript's stdin
481 osapipe.write(script)
482 rc = osapipe.close()
483 return not rc
484
485 # Don't clear _tryorder or _browsers since OS X can use above Unix support
486 # (but we prefer using the OS X specific stuff)
487 register("MacOSX", None, MacOSX('default'), -1)
488
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000489
Martin v. Löwis3a89b2b2001-11-25 14:35:58 +0000490#
491# Platform support for OS/2
492#
493
Georg Brandle8f24432005-10-03 14:16:44 +0000494if sys.platform[:3] == "os2" and _iscommand("netscape"):
495 _tryorder = []
496 _browsers = {}
Martin v. Löwis3a89b2b2001-11-25 14:35:58 +0000497 register("os2netscape", None,
Georg Brandle8f24432005-10-03 14:16:44 +0000498 GenericBrowser("start netscape %s"), -1)
499
Martin v. Löwis3a89b2b2001-11-25 14:35:58 +0000500
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000501# OK, now that we know what the default preference orders for each
502# platform are, allow user to override them with the BROWSER variable.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000503if "BROWSER" in os.environ:
Georg Brandle8f24432005-10-03 14:16:44 +0000504 _userchoices = os.environ["BROWSER"].split(os.pathsep)
505 _userchoices.reverse()
Skip Montanarocdab3bf2001-07-18 20:03:32 +0000506
Georg Brandle8f24432005-10-03 14:16:44 +0000507 # Treat choices in same way as if passed into get() but do register
508 # and prepend to _tryorder
509 for cmdline in _userchoices:
510 if cmdline != '':
511 _synthesize(cmdline, -1)
512 cmdline = None # to make del work if _userchoices was empty
513 del cmdline
514 del _userchoices
Skip Montanarocdab3bf2001-07-18 20:03:32 +0000515
Skip Montanarocdab3bf2001-07-18 20:03:32 +0000516# what to do if _tryorder is now empty?
Georg Brandle8f24432005-10-03 14:16:44 +0000517
518
519def main():
520 import getopt
521 usage = """Usage: %s [-n | -t] url
522 -n: open new window
523 -t: open new tab""" % sys.argv[0]
524 try:
525 opts, args = getopt.getopt(sys.argv[1:], 'ntd')
526 except getopt.error, msg:
527 print >>sys.stderr, msg
528 print >>sys.stderr, usage
529 sys.exit(1)
530 new_win = 0
531 for o, a in opts:
532 if o == '-n': new_win = 1
533 elif o == '-t': new_win = 2
534 if len(args) <> 1:
535 print >>sys.stderr, usage
536 sys.exit(1)
537
538 url = args[0]
539 open(url, new_win)
540
541if __name__ == "__main__":
542 main()