blob: b589d91b01fdab2c09e8fa78be3a466127375e66 [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()
Tim Peters536cf992005-12-25 23:18:31 +000099 if os.path.isfile(cmd) and (cmd.endswith(".exe") or
Georg Brandle8f24432005-10-03 14:16:44 +0000100 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
Tim Peters536cf992005-12-25 23:18:31 +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 Brandl1cb179e2005-11-09 21:42:48 +0000183 cmd = "%s %s" % (self.name, url)
184 if self.remote_background:
185 cmd += " &"
Georg Brandle8f24432005-10-03 14:16:44 +0000186 # bad return status, try again with simpler command
Georg Brandl1cb179e2005-11-09 21:42:48 +0000187 rc = os.system(cmd)
Fred Drake3f8f1642001-07-19 03:46:26 +0000188 return not rc
189
190 def open(self, url, new=0, autoraise=1):
Georg Brandle8f24432005-10-03 14:16:44 +0000191 assert "'" not in url
192 if new == 0:
193 action = self.remote_action
194 elif new == 1:
195 action = self.remote_action_newwin
196 elif new == 2:
197 if self.remote_action_newtab is None:
198 action = self.remote_action_newwin
199 else:
200 action = self.remote_action_newtab
Fred Drake3f8f1642001-07-19 03:46:26 +0000201 else:
Georg Brandle8f24432005-10-03 14:16:44 +0000202 raise Error("Bad 'new' parameter to open(); expected 0, 1, or 2, got %s" % new)
203 return self._remote(url, action % url, autoraise)
Fred Drake3f8f1642001-07-19 03:46:26 +0000204
205
Georg Brandle8f24432005-10-03 14:16:44 +0000206class Mozilla(UnixBrowser):
207 """Launcher class for Mozilla/Netscape browsers."""
Neal Norwitz8dd28eb2002-10-10 22:49:29 +0000208
Georg Brandle8f24432005-10-03 14:16:44 +0000209 raise_opts = ("-noraise", "-raise")
Neal Norwitz8dd28eb2002-10-10 22:49:29 +0000210
Georg Brandle8f24432005-10-03 14:16:44 +0000211 remote_cmd = '-remote'
212 remote_action = "openURL(%s)"
213 remote_action_newwin = "openURL(%s,new-window)"
214 remote_action_newtab = "openURL(%s,new-tab)"
Georg Brandl1cb179e2005-11-09 21:42:48 +0000215 remote_background = True
Neal Norwitz8dd28eb2002-10-10 22:49:29 +0000216
Georg Brandle8f24432005-10-03 14:16:44 +0000217Netscape = Mozilla
Neal Norwitz8dd28eb2002-10-10 22:49:29 +0000218
219
Georg Brandle8f24432005-10-03 14:16:44 +0000220class Galeon(UnixBrowser):
221 """Launcher class for Galeon/Epiphany browsers."""
222
223 raise_opts = ("-noraise", "")
224 remote_action = "-n '%s'"
225 remote_action_newwin = "-w '%s'"
226
227 remote_background = True
228
229
230class Konqueror(BaseBrowser):
Fred Drake3f8f1642001-07-19 03:46:26 +0000231 """Controller for the KDE File Manager (kfm, or Konqueror).
232
233 See http://developer.kde.org/documentation/other/kfmclient.html
234 for more information on the Konqueror remote-control interface.
235
236 """
Fred Drake3f8f1642001-07-19 03:46:26 +0000237
Georg Brandle8f24432005-10-03 14:16:44 +0000238 def _remote(self, url, action):
239 # kfmclient is the new KDE way of opening URLs.
Neal Norwitz520cdf72002-10-11 22:04:22 +0000240 cmd = "kfmclient %s >/dev/null 2>&1" % action
Fred Drake3f8f1642001-07-19 03:46:26 +0000241 rc = os.system(cmd)
Georg Brandle8f24432005-10-03 14:16:44 +0000242 # Fall back to other variants.
Fred Drake3f8f1642001-07-19 03:46:26 +0000243 if rc:
Georg Brandle8f24432005-10-03 14:16:44 +0000244 if _iscommand("konqueror"):
245 rc = os.system(self.name + " --silent '%s' &" % url)
246 elif _iscommand("kfm"):
Georg Brandl1cb179e2005-11-09 21:42:48 +0000247 rc = os.system(self.name + " -d '%s' &" % url)
Fred Drake3f8f1642001-07-19 03:46:26 +0000248 return not rc
249
Georg Brandle8f24432005-10-03 14:16:44 +0000250 def open(self, url, new=0, autoraise=1):
Fred Drake3f8f1642001-07-19 03:46:26 +0000251 # XXX Currently I know no way to prevent KFM from
252 # opening a new win.
Neal Norwitz520cdf72002-10-11 22:04:22 +0000253 assert "'" not in url
Georg Brandle8f24432005-10-03 14:16:44 +0000254 if new == 2:
255 action = "newTab '%s'" % url
256 else:
257 action = "openURL '%s'" % url
258 ok = self._remote(url, action)
259 return ok
Fred Drake3f8f1642001-07-19 03:46:26 +0000260
261
Georg Brandle8f24432005-10-03 14:16:44 +0000262class Opera(UnixBrowser):
263 "Launcher class for Opera browser."
264
265 raise_opts = ("", "-raise")
266
267 remote_cmd = '-remote'
268 remote_action = "openURL(%s)"
269 remote_action_newwin = "openURL(%s,new-window)"
270 remote_action_newtab = "openURL(%s,new-page)"
Georg Brandl1cb179e2005-11-09 21:42:48 +0000271 remote_background = True
Georg Brandle8f24432005-10-03 14:16:44 +0000272
273
274class Elinks(UnixBrowser):
275 "Launcher class for Elinks browsers."
276
277 remote_cmd = '-remote'
278 remote_action = "openURL(%s)"
279 remote_action_newwin = "openURL(%s,new-window)"
280 remote_action_newtab = "openURL(%s,new-tab)"
281
282 def _remote(self, url, action, autoraise):
283 # elinks doesn't like its stdout to be redirected -
284 # it uses redirected stdout as a signal to do -dump
285 cmd = "%s %s '%s' 2>/dev/null" % (self.name,
286 self.remote_cmd, action)
287 rc = os.system(cmd)
288 if rc:
289 rc = os.system("%s %s" % (self.name, url))
290 return not rc
291
292
293class Grail(BaseBrowser):
Fred Drake3f8f1642001-07-19 03:46:26 +0000294 # There should be a way to maintain a connection to Grail, but the
295 # Grail remote control protocol doesn't really allow that at this
296 # point. It probably neverwill!
297 def _find_grail_rc(self):
298 import glob
299 import pwd
300 import socket
301 import tempfile
302 tempdir = os.path.join(tempfile.gettempdir(),
303 ".grail-unix")
Fred Drake16623fe2001-10-13 16:00:52 +0000304 user = pwd.getpwuid(os.getuid())[0]
Fred Drake3f8f1642001-07-19 03:46:26 +0000305 filename = os.path.join(tempdir, user + "-*")
306 maybes = glob.glob(filename)
307 if not maybes:
308 return None
309 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
310 for fn in maybes:
311 # need to PING each one until we find one that's live
312 try:
313 s.connect(fn)
314 except socket.error:
315 # no good; attempt to clean it out, but don't fail:
316 try:
317 os.unlink(fn)
318 except IOError:
319 pass
320 else:
321 return s
322
323 def _remote(self, action):
324 s = self._find_grail_rc()
325 if not s:
326 return 0
327 s.send(action)
328 s.close()
329 return 1
330
331 def open(self, url, new=0, autoraise=1):
332 if new:
Georg Brandle8f24432005-10-03 14:16:44 +0000333 ok = self._remote("LOADNEW " + url)
Fred Drake3f8f1642001-07-19 03:46:26 +0000334 else:
Georg Brandle8f24432005-10-03 14:16:44 +0000335 ok = self._remote("LOAD " + url)
336 return ok
Fred Drake3f8f1642001-07-19 03:46:26 +0000337
Fred Drakec70b4482000-07-09 16:45:56 +0000338
Tim Peters658cba62001-02-09 20:06:00 +0000339#
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000340# Platform support for Unix
341#
Fred Drakec70b4482000-07-09 16:45:56 +0000342
Georg Brandle8f24432005-10-03 14:16:44 +0000343# These are the right tests because all these Unix browsers require either
344# a console terminal or an X display to run.
Fred Drakec70b4482000-07-09 16:45:56 +0000345
Neal Norwitz196f7332005-10-04 03:17:49 +0000346def register_X_browsers():
Georg Brandle8f24432005-10-03 14:16:44 +0000347 # The default Gnome browser
348 if _iscommand("gconftool-2"):
349 # get the web browser string from gconftool
350 gc = 'gconftool-2 -g /desktop/gnome/url-handlers/http/command'
351 out = os.popen(gc)
352 commd = out.read().strip()
353 retncode = out.close()
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000354
Georg Brandle8f24432005-10-03 14:16:44 +0000355 # if successful, register it
356 if retncode == None and len(commd) != 0:
357 register("gnome", None, GenericBrowser(
358 commd + " '%s' >/dev/null &"))
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000359
Georg Brandl4a5a9182005-11-22 19:18:01 +0000360 # First, the Mozilla/Netscape browsers
361 for browser in ("mozilla-firefox", "firefox",
362 "mozilla-firebird", "firebird",
363 "mozilla", "netscape"):
364 if _iscommand(browser):
365 register(browser, None, Mozilla(browser))
366
Georg Brandle8f24432005-10-03 14:16:44 +0000367 # Konqueror/kfm, the KDE browser.
Georg Brandlb9801132005-10-08 20:47:38 +0000368 if _iscommand("kfm"):
369 register("kfm", Konqueror, Konqueror("kfm"))
370 elif _iscommand("konqueror"):
371 register("konqueror", Konqueror, Konqueror("konqueror"))
Neal Norwitz8dd28eb2002-10-10 22:49:29 +0000372
Georg Brandle8f24432005-10-03 14:16:44 +0000373 # Gnome's Galeon and Epiphany
374 for browser in ("galeon", "epiphany"):
375 if _iscommand(browser):
376 register(browser, None, Galeon(browser))
Gustavo Niemeyer1456fde2002-11-25 17:25:04 +0000377
Georg Brandle8f24432005-10-03 14:16:44 +0000378 # Skipstone, another Gtk/Mozilla based browser
379 if _iscommand("skipstone"):
380 register("skipstone", None, GenericBrowser("skipstone '%s' &"))
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000381
Georg Brandle8f24432005-10-03 14:16:44 +0000382 # Opera, quite popular
383 if _iscommand("opera"):
384 register("opera", None, Opera("opera"))
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000385
Georg Brandle8f24432005-10-03 14:16:44 +0000386 # Next, Mosaic -- old but still in use.
387 if _iscommand("mosaic"):
388 register("mosaic", None, GenericBrowser("mosaic '%s' &"))
Fred Drake3f8f1642001-07-19 03:46:26 +0000389
Georg Brandle8f24432005-10-03 14:16:44 +0000390 # Grail, the Python browser. Does anybody still use it?
391 if _iscommand("grail"):
392 register("grail", Grail, None)
Fred Drake3f8f1642001-07-19 03:46:26 +0000393
Neal Norwitz196f7332005-10-04 03:17:49 +0000394# Prefer X browsers if present
395if os.environ.get("DISPLAY"):
396 register_X_browsers()
397
Georg Brandle8f24432005-10-03 14:16:44 +0000398# Also try console browsers
399if os.environ.get("TERM"):
400 # The Links/elinks browsers <http://artax.karlin.mff.cuni.cz/~mikulas/links/>
401 if _iscommand("links"):
402 register("links", None, GenericBrowser("links '%s'"))
403 if _iscommand("elinks"):
404 register("elinks", None, Elinks("elinks"))
405 # The Lynx browser <http://lynx.isc.org/>, <http://lynx.browser.org/>
406 if _iscommand("lynx"):
407 register("lynx", None, GenericBrowser("lynx '%s'"))
408 # The w3m browser <http://w3m.sourceforge.net/>
409 if _iscommand("w3m"):
410 register("w3m", None, GenericBrowser("w3m '%s'"))
Fred Drake3f8f1642001-07-19 03:46:26 +0000411
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000412#
413# Platform support for Windows
414#
Fred Drakec70b4482000-07-09 16:45:56 +0000415
416if sys.platform[:3] == "win":
Georg Brandle8f24432005-10-03 14:16:44 +0000417 class WindowsDefault(BaseBrowser):
418 def open(self, url, new=0, autoraise=1):
419 os.startfile(url)
420 return True # Oh, my...
421
422 _tryorder = []
423 _browsers = {}
424 # Prefer mozilla/netscape/opera if present
425 for browser in ("firefox", "firebird", "mozilla", "netscape", "opera"):
426 if _iscommand(browser):
427 register(browser, None, GenericBrowser(browser + ' %s'))
Fred Drakec70b4482000-07-09 16:45:56 +0000428 register("windows-default", WindowsDefault)
Fred Drakec70b4482000-07-09 16:45:56 +0000429
Fred Drakec70b4482000-07-09 16:45:56 +0000430#
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000431# Platform support for MacOS
432#
Fred Drakec70b4482000-07-09 16:45:56 +0000433
434try:
435 import ic
436except ImportError:
437 pass
438else:
Georg Brandle8f24432005-10-03 14:16:44 +0000439 class InternetConfig(BaseBrowser):
440 def open(self, url, new=0, autoraise=1):
441 ic.launchurl(url)
442 return True # Any way to get status?
443
444 register("internet-config", InternetConfig, update_tryorder=-1)
445
446if sys.platform == 'darwin':
447 # Adapted from patch submitted to SourceForge by Steven J. Burr
448 class MacOSX(BaseBrowser):
449 """Launcher class for Aqua browsers on Mac OS X
450
451 Optionally specify a browser name on instantiation. Note that this
452 will not work for Aqua browsers if the user has moved the application
453 package after installation.
454
455 If no browser is specified, the default browser, as specified in the
456 Internet System Preferences panel, will be used.
457 """
458 def __init__(self, name):
459 self.name = name
460
461 def open(self, url, new=0, autoraise=1):
462 assert "'" not in url
463 # new must be 0 or 1
464 new = int(bool(new))
465 if self.name == "default":
466 # User called open, open_new or get without a browser parameter
Georg Brandl1cb179e2005-11-09 21:42:48 +0000467 script = 'open location "%s"' % url.replace('"', '%22') # opens in default browser
Georg Brandle8f24432005-10-03 14:16:44 +0000468 else:
469 # User called get and chose a browser
470 if self.name == "OmniWeb":
471 toWindow = ""
472 else:
473 # Include toWindow parameter of OpenURL command for browsers
474 # that support it. 0 == new window; -1 == existing
475 toWindow = "toWindow %d" % (new - 1)
Georg Brandl1cb179e2005-11-09 21:42:48 +0000476 cmd = 'OpenURL "%s"' % url.replace('"', '%22')
Georg Brandle8f24432005-10-03 14:16:44 +0000477 script = '''tell application "%s"
478 activate
479 %s %s
480 end tell''' % (self.name, cmd, toWindow)
481 # Open pipe to AppleScript through osascript command
482 osapipe = os.popen("osascript", "w")
483 if osapipe is None:
484 return False
485 # Write script to osascript's stdin
486 osapipe.write(script)
487 rc = osapipe.close()
488 return not rc
489
490 # Don't clear _tryorder or _browsers since OS X can use above Unix support
491 # (but we prefer using the OS X specific stuff)
492 register("MacOSX", None, MacOSX('default'), -1)
493
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000494
Martin v. Löwis3a89b2b2001-11-25 14:35:58 +0000495#
496# Platform support for OS/2
497#
498
Georg Brandle8f24432005-10-03 14:16:44 +0000499if sys.platform[:3] == "os2" and _iscommand("netscape"):
500 _tryorder = []
501 _browsers = {}
Martin v. Löwis3a89b2b2001-11-25 14:35:58 +0000502 register("os2netscape", None,
Georg Brandle8f24432005-10-03 14:16:44 +0000503 GenericBrowser("start netscape %s"), -1)
504
Martin v. Löwis3a89b2b2001-11-25 14:35:58 +0000505
Eric S. Raymondf7f18512001-01-23 13:16:32 +0000506# OK, now that we know what the default preference orders for each
507# platform are, allow user to override them with the BROWSER variable.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000508if "BROWSER" in os.environ:
Georg Brandle8f24432005-10-03 14:16:44 +0000509 _userchoices = os.environ["BROWSER"].split(os.pathsep)
510 _userchoices.reverse()
Skip Montanarocdab3bf2001-07-18 20:03:32 +0000511
Georg Brandle8f24432005-10-03 14:16:44 +0000512 # Treat choices in same way as if passed into get() but do register
513 # and prepend to _tryorder
514 for cmdline in _userchoices:
515 if cmdline != '':
516 _synthesize(cmdline, -1)
517 cmdline = None # to make del work if _userchoices was empty
518 del cmdline
519 del _userchoices
Skip Montanarocdab3bf2001-07-18 20:03:32 +0000520
Skip Montanarocdab3bf2001-07-18 20:03:32 +0000521# what to do if _tryorder is now empty?
Georg Brandle8f24432005-10-03 14:16:44 +0000522
523
524def main():
525 import getopt
526 usage = """Usage: %s [-n | -t] url
527 -n: open new window
528 -t: open new tab""" % sys.argv[0]
529 try:
530 opts, args = getopt.getopt(sys.argv[1:], 'ntd')
531 except getopt.error, msg:
532 print >>sys.stderr, msg
533 print >>sys.stderr, usage
534 sys.exit(1)
535 new_win = 0
536 for o, a in opts:
537 if o == '-n': new_win = 1
538 elif o == '-t': new_win = 2
539 if len(args) <> 1:
540 print >>sys.stderr, usage
541 sys.exit(1)
542
543 url = args[0]
544 open(url, new_win)
545
546if __name__ == "__main__":
547 main()