Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Side by Side Diff: install_test/chrome_installer_win.py

Issue 10384104: Chrome updater test framework (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome/test/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | install_test/install_test.py » ('j') | install_test/install_test.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Provides an interface for installing Chrome.
7
8 At present the only platform it supports is Windows.
9 """
10
11 import _winreg
12 import ctypes
13 from ctypes import wintypes, windll
14 import httplib
15 import logging
16 import os
17 import shutil
18 import socket
19 import subprocess
20 import tempfile
21 import urllib
22
23
24 class InstallationType(object):
25 """Defines the Chrome installation types."""
26 SYSTEM = 1
27 USER = 2
28
29
30 def Install(installer_path, install_type, build, options):
kkania 2012/10/02 17:05:16 change build->version or build_no
nkang 2012/10/03 22:12:01 Changed build to version.
31 """Installs the specified Chrome build.
32
33 Args:
34 installer_path: Path to the Chrome installer.
35 install_type: Type of installation (i.e., system or user).
36 build: Chrome build number.
37 options: Additional installation options.
38
39 Returns:
40 An instance of ChromeInstallation.
41 """
42 current = ChromeInstallation.GetCurrent()
43 if current:
44 # Make sure new build can be installed over existing Chrome build.
45 if (current.GetType() == InstallationType.SYSTEM and
46 install_type == InstallationType.USER):
47 raise RuntimeError('System level Chrome exists, aborting user level '
48 'installation.')
49 # Confirm the new Chrome build is higher than the installed build.
50 if current.GetVersion() >= build:
kkania 2012/10/02 17:05:16 You can't do a straight string comparison of versi
nkang 2012/10/03 22:12:01 Wrote a new method that separates each identifier
51 raise RuntimeError('Specify a version higher than the one already '
kkania 2012/10/02 17:05:16 it is nice to explain to the user what to do with
nkang 2012/10/03 22:12:01 Changed the error message.
52 'installed.')
53 options.append('--install')
54 options.append('--do-not-launch-chrome')
55 logging.info('Installing Chrome build %s...' % build)
56 args = [installer_path]
57 args.extend(options)
58 if subprocess.Popen(args).wait() != 0:
59 raise RuntimeError('Chrome installation for build %s failed.' % build)
60 logging.info('Installation complete.')
61 return ChromeInstallation.GetCurrent()
62
63
64 class ChromeRegistryValues(object):
65 """Defines the Chrome registry key values."""
66 PRODUCT_VERSION = 'pv'
67 UNINSTALL_STRING = 'UninstallString'
68 UNINSTALL_ARGUMENTS = 'UninstallArguments'
69
70
71 class ChromeRegistryKeys(object):
72 """An interface for accessing and manipulating Chrome registry keys."""
73
74 _hkey_local = r'SOFTWARE\Wow6432Node\Google\Update'
kkania 2012/10/02 17:05:16 i know you were trying to follow the hkey style, b
nkang 2012/10/03 22:12:01 That's what I had earlier, but Nirnimesh asked me
75 _hkey_user = _hkey_local.replace(r'\Wow6432Node', '')
76 _chrome_version = r'Clients\{8A69D345-D564-463C-AFF1-A69D9E530F96}'
77 _chrome_args = r'ClientState\{8A69D345-D564-463C-AFF1-A69D9E530F96}'
78
79 def _GetKeyName(self, install_type, value):
80 """Gets the registry key name for the specified value.
81
82 Args:
83 install_type: Type of installation, must be InstallationType type.
84 value: ChromeRegistryValues type for which the key name is required.
85
86 Returns:
87 A string representing the full key name of the specified key value.
88 """
89 key_name = None
90 if install_type == InstallationType.USER:
91 key_name = self._hkey_user
92 elif install_type == InstallationType.SYSTEM:
93 key_name = self._hkey_local
94 if value == ChromeRegistryValues.PRODUCT_VERSION:
95 return '%s\%s' % (key_name, self._chrome_version)
kkania 2012/10/02 17:05:16 use \\ or r'%s\%s'
nkang 2012/10/03 22:12:01 Using 'r' now.
96 elif value == ChromeRegistryValues.UNINSTALL_ARGUMENTS:
97 return '%s\%s' % (key_name, self._chrome_args)
98 elif value == ChromeRegistryValues.UNINSTALL_STRING:
99 return '%s\%s' % (key_name, self._chrome_args)
100 raise RuntimeError('Invalid registry value.')
101
102 def _GetRegistryType(self, install_type):
103 """Determines the registry key to use based on installation type.
104
105 Args:
106 install_type: Type of installation, must be InstallationType type.
107
108 Returns:
109 A long representing HKLM or HKCU, depending on installation type.
110 """
111 if install_type == InstallationType.SYSTEM:
112 return _winreg.HKEY_LOCAL_MACHINE
113 elif install_type == InstallationType.USER:
114 return _winreg.HKEY_CURRENT_USER
115 raise RuntimeError('Invalid installation type.')
116
117 def DoesKeyExist(self, install_type, subkey):
118 """Determines if a particular key exists in the registry.
119
120 Args:
121 install_type: Type of installation, must be InstallationType type.
122 subkey: Subkey to look up. It must be a ChromeRegistryValues type.
123
124 Returns:
125 True if the key exists, otherwise False.
126 """
127 key = self._GetRegistryType(install_type)
128 key_name = self._GetKeyName(install_type, subkey)
129 try:
130 hkey = _winreg.OpenKey(key, key_name)
131 except _winreg.error:
132 return False
133 if not hkey.handle:
134 return False
135 hkey.Close()
136 return True
137
138 def GetKeyValue(self, install_type, subkey):
139 """Gets value of the specified subkey from the registry.
140
141 Args:
142 install_type: Type of installation, must be InstallationType type.
143 subkey: ChromeRegistryValue type representing the value to be returned.
144
145 Returns:
146 A string representing the subkey value.
147 """
148 key = self._GetRegistryType(install_type)
149 key_name = self._GetKeyName(install_type, subkey)
150 hkey = _winreg.OpenKey(key, key_name)
151 reg_value = str(_winreg.QueryValueEx(hkey, subkey)[0])
152 hkey.Close()
153 return reg_value
154
155 def DeleteRegistryEntries(self, install_type):
156 """Deletes chrome registry settings.
157
158 Args:
159 install_type: Type of installation, must be InstallationType type.
160 """
161 reg_type = self._GetRegistryType(install_type)
162 key_name = self._GetKeyName(install_type,
163 ChromeRegistryValues.UNINSTALL_ARGUMENTS)
164 root = key_name[:key_name.rfind('\\')]
165 child = key_name[key_name.rfind('\\') + 1:]
166 key = _winreg.OpenKey(reg_type, root, 0, _winreg.KEY_ALL_ACCESS)
167 _winreg.DeleteKey(key, child)
168 key.Close()
169
170
171 class ChromeInstallation(object):
172 """Provides pertinent information about the installed Chrome version.
173
174 The type of Chrome version must be passed as an argument to the constructor,
175 (i.e. - user or system level).
176 """
177
178 _CSIDL_COMMON_APPDATA = 0x1C
179 _CSIDL_PROGRAM_FILESX86 = 0x2A
180
181 def __init__(self, install_type):
182 assert(install_type == InstallationType.SYSTEM or
183 install_type == InstallationType.USER)
184 self._type = install_type
185 self._regedit = ChromeRegistryKeys()
186
187 def GetType(self):
188 """Returns the current installation type."""
189 return self._type
190
191 def GetVersion(self):
192 """Returns the installed version of Chrome."""
193 return self._regedit.GetKeyValue(self._type,
194 ChromeRegistryValues.PRODUCT_VERSION)
195
196 def _GetWinLocalFolder(self, ftype=_CSIDL_COMMON_APPDATA):
197 """Returns full path of the 'Local' folder on Windows.
198
199 Args:
200 ftype: Location to look up, which could vary based on installation type.
201
202 Returns:
203 A String representing the folder path if successful, otherwise an empty
204 string.
205 """
206 SHGetFolderPathW = windll.shell32.SHGetFolderPathW
207 SHGetFolderPathW.argtypes = [wintypes.HWND,
208 ctypes.c_int,
209 wintypes.HANDLE,
210 wintypes.DWORD,
211 wintypes.LPCWSTR]
212 path_buf = wintypes.create_unicode_buffer(wintypes.MAX_PATH)
213 result = SHGetFolderPathW(0, ftype, 0, 0, path_buf)
214 return str(path_buf.value)
215
216 def _GetUninstallString(self):
217 """Returns the Chrome uninstall string from the registry."""
218 return self._regedit.GetKeyValue(self._type,
219 ChromeRegistryValues.UNINSTALL_STRING)
220
221 def _GetUninstallArguments(self):
222 """Returns the Chrome uninstall arguments from the registry."""
223 return self._regedit.GetKeyValue(self._type,
224 ChromeRegistryValues.UNINSTALL_ARGUMENTS)
225
226 def GetExePath(self):
227 """Returns Chrome binary location based on installation type.
228
229 Currently this method only returns the location of the Chrome binary.
230 It does not support Chromium.
231 """
232 if self._type == InstallationType.USER:
233 folder_id = self._CSIDL_COMMON_APPDATA
234 elif self._type == InstallationType.SYSTEM:
235 folder_id = self._CSIDL_PROGRAM_FILESX86
236 chrome_path = os.path.join(self._GetWinLocalFolder(folder_id), 'Google',
237 'Chrome', 'Application', 'chrome.exe')
238 return (chrome_path if os.path.exists(chrome_path) else '')
239
240 @staticmethod
241 def GetCurrent():
242 """Determines Chrome installation type.
243
244 Returns:
245 ChromeInstallation object if Chrome is present, otherwise None.
246 """
247 registry = ChromeRegistryKeys()
248 if registry.DoesKeyExist(InstallationType.SYSTEM,
249 ChromeRegistryValues.PRODUCT_VERSION):
250 return ChromeInstallation(InstallationType.SYSTEM)
251 elif registry.DoesKeyExist(InstallationType.USER,
252 ChromeRegistryValues.PRODUCT_VERSION):
253 return ChromeInstallation(InstallationType.USER)
254 return None
255
256 def Uninstall(self):
257 """Uninstalls Chrome."""
258 chrome_path = self.GetExePath()
259 reg_opts = self._GetUninstallArguments()
260 uninstall_str = self._GetUninstallString()
261 options = '%s --force-uninstall' % (reg_opts)
262 if self._type == InstallationType.SYSTEM:
263 options += ' --system-level'
264 if not os.path.exists(chrome_path):
265 raise RuntimeError('Could not find chrome, aborting uninstall.')
266 logging.info('Launching Chrome installer...')
267 cmd = '"%s" %s' % (uninstall_str, options)
268 subprocess.call(cmd)
269 if not os.path.exists(chrome_path):
270 logging.info('Chrome was uninstalled successfully...')
271 logging.info('Deleting registry entries...')
272 self._regedit.DeleteRegistryEntries(self._type)
273 logging.info('Uninstall complete.')
274 else:
275 raise RuntimeError('Uninstall failed.')
OLDNEW
« no previous file with comments | « no previous file | install_test/install_test.py » ('j') | install_test/install_test.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698