1#!/usr/bin/env python
2# Copyright 2009 Google Inc. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16"""Wrapper for webbrowser library, to invoke the http handler on win32."""
17
18__author__ = 'tstromberg@google.com (Thomas Stromberg)'
19
20import os.path
21import subprocess
22import sys
23import traceback
24import webbrowser
25
26import util
27
28
29def output(string):
30  print string
31
32
33def create_win32_http_cmd(url):
34  """Create a command-line tuple to launch a web browser for a given URL.
35
36  Args:
37    url: string
38
39  Returns:
40    tuple of: (executable, arg1, arg2, ...)
41
42  At the moment, this ignores all default arguments to the browser.
43  TODO(tstromberg): Properly parse the command-line arguments.
44  """
45  browser_type = None
46  try:
47    key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
48                          'Software\Classes\http\shell\open\command')
49    browser_type = 'user'
50  except WindowsError:
51    key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
52                          'Software\Classes\http\shell\open\command')
53    browser_type = 'machine'
54  except:
55    return False
56
57  cmd = _winreg.EnumValue(key, 0)[1]
58  # "C:\blah blah\iexplore.exe" -nohome
59  # "C:\blah blah\firefox.exe" -requestPending -osint -url "%1"
60  if '"' in cmd:
61    executable = cmd.split('"')[1]
62  else:
63    executable = cmd.split(' ')[0]
64
65  if not os.path.exists(executable):
66    output('$ Default HTTP browser does not exist: %s' % executable)
67    return False
68  else:
69    output('$ %s HTTP handler: %s' % (browser_type, executable))
70  return (executable, url)
71
72
73def open(url):
74  """Opens a URL, overriding the normal webbrowser.open methods for sanity."""
75
76  try:
77    webbrowser.open(url, new=1, autoraise=True)
78  # If the user is missing the osascript binary - see
79  # http://code.google.com/p/namebench/issues/detail?id=88
80  except:
81    output('Failed to open: [%s]: %s' % (url, util.GetLastExceptionString()))
82    if os.path.exists('/usr/bin/open'):
83      try:
84        output('trying open: %s' % url)
85        p = subprocess.Popen(('open', url))
86        p.wait()
87      except:
88        output('open did not seem to work: %s' % util.GetLastExceptionString())
89    elif sys.platform[:3] == 'win':
90      try:
91        output('trying default Windows controller: %s' % url)
92        controller = webbrowser.get('windows-default')
93        controller.open_new(url)
94      except:
95        output('WindowsController did not work: %s' % util.GetLastExceptionString())
96
97
98# *NOTE*: EVIL IMPORT SIDE EFFECTS AHEAD!
99#
100# If we are running on Windows, register the WindowsHttpDefault class.
101if sys.platform[:3] == 'win':
102  import _winreg
103
104  # We don't want to load this class by default, because Python 2.4 doesn't have BaseBrowser.
105
106  class WindowsHttpDefault(webbrowser.BaseBrowser):
107    """Provide an alternate open class for Windows user, using the http handler."""
108
109    def open(self, url, new=0, autoraise=1):
110      command_args = create_win32_http_cmd(url)
111      if not command_args:
112        output('$ Could not find HTTP handler')
113        return False
114
115      output('command_args:')
116      output(command_args)
117      # Avoid some unicode path issues by moving our current directory
118      old_pwd = os.getcwd()
119      os.chdir('C:\\')
120      try:
121        _unused = subprocess.Popen(command_args)
122        os.chdir(old_pwd)
123        return True
124      except:
125        traceback.print_exc()
126        output('$ Failed to run HTTP handler, trying next browser.')
127        os.chdir(old_pwd)
128        return False
129
130  webbrowser.register('windows-http', WindowsHttpDefault, update_tryorder=-1)
131