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

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, 4 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
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 NOT_INSTALLED = 0
27 SYSTEM = 1
28 USER = 2
29
30
31 class ChromeRegistryValues(object):
32 """Defines the Chrome registry key values."""
33 PRODUCT_VERSION = 'pv'
34 UNINSTALL_STRING = 'UninstallString'
35 UNINSTALL_ARGUMENTS = 'UninstallArguments'
36
37
38 def Install(installer_path, install_type, build, options):
39 """Installs the specified Chrome build.
40
41 Args:
42 installer_path: Path to the Chrome installer.
43 install_type: Type of installation (i.e., system or user).
44 build: Chrome build number.
45 options: Additional installation options.
46
47 Returns:
48 An instance of ChromeInstallation.
49 """
50 def _DoPreliminaryChecks(regedit):
51 """Validates the test parameters and Chrome version.
52
53 Checks if a Chrome version is already installed on the system. If so it
54 confirms that the version specified by the user is higher than the one
55 currently installed. It also checks to make sure the installation type
56 is valid, as a user level version cannot be installed over an existing
57 system level version of Chrome.
58
59 Args:
60 regedit: ChromeRegistryKeys object.
61 """
62 current_type = InstallationType.NOT_INSTALLED
63 # Check if Chrome is already installed on the system.
64 if regedit.DoesKeyExist(InstallationType.USER,
65 ChromeRegistryValues.PRODUCT_VERSION):
66 current_type = InstallationType.USER
67 elif regedit.DoesKeyExist(InstallationType.SYSTEM,
68 ChromeRegistryValues.PRODUCT_VERSION):
69 current_type = InstallationType.SYSTEM
70 if current_type:
71 # Make sure new build can be installed over existing Chrome build.
72 if (current_type == InstallationType.SYSTEM and
73 install_type == InstallationType.USER):
74 raise RuntimeError('System level Chrome exists, aborting user level '
75 'installation.')
76 build_num = regedit.GetKeyValue(current_type,
77 ChromeRegistryValues.PRODUCT_VERSION)
78 # Confirm the new Chrome build is higher than the installed build.
79 if build_num >= build:
80 raise RuntimeError('Specify a version higher than the one already '
81 'installed.')
82
83 regedit = ChromeRegistryKeys()
84 _DoPreliminaryChecks(regedit)
85 options.append('--install')
86 options.append('--do-not-launch-chrome')
87 logging.info('Launching Chrome installer...')
88 args = [installer_path]
89 args.extend(options)
90 if subprocess.Popen(args).wait() != 0:
91 raise RuntimeError('Chrome installation for build %s failed.' % build)
92 logging.info('Installation complete.')
93 return ChromeInstallation.GetCurrent()
94
95
96 class ChromeRegistryKeys(object):
97 """An interface for accessing and manipulating Chrome registry keys."""
98
99 _hkey_local = r'SOFTWARE\Wow6432Node\Google\Update'
100 _hkey_user = _hkey_local.replace(r'\Wow6432Node', '')
101 _chrome_version = r'Clients\{8A69D345-D564-463C-AFF1-A69D9E530F96}'
102 _chrome_args = r'ClientState\{8A69D345-D564-463C-AFF1-A69D9E530F96}'
103
104 def _GetKeyName(self, install_type, value):
105 """Gets the registry key name for the specified value.
106
107 Args:
108 install_type: Type of installation, must be InstallationType type.
109 value: ChromeRegistryValues type for which the key name is required.
110
111 Returns:
112 A string representing the full key name of the specified key value.
113 """
114 key_name = None
115 if install_type == InstallationType.USER:
116 key_name = self._hkey_user
117 elif install_type == InstallationType.SYSTEM:
118 key_name = self._hkey_local
119 if value == ChromeRegistryValues.PRODUCT_VERSION:
120 return '%s\%s' % (key_name, self._chrome_version)
121 elif value == ChromeRegistryValues.UNINSTALL_ARGUMENTS:
122 return '%s\%s' % (key_name, self._chrome_args)
123 elif value == ChromeRegistryValues.UNINSTALL_STRING:
124 return '%s\%s' % (key_name, self._chrome_args)
125 raise RuntimeError('Invalid registry value.')
126
127 def _GetRegistryType(self, install_type):
128 """Determines the registry key to use based on installation type.
129
130 Args:
131 install_type: Type of installation, must be InstallationType type.
132
133 Returns:
134 A long representing HKLM or HKCU, depending on installation type.
135 """
136 if install_type == InstallationType.SYSTEM:
137 return _winreg.HKEY_LOCAL_MACHINE
138 elif install_type == InstallationType.USER:
139 return _winreg.HKEY_CURRENT_USER
140 raise RuntimeError('Invalid installation type.')
141
142 def DoesKeyExist(self, install_type, subkey):
143 """Determines if a particular key exists in the registry.
144
145 Args:
146 install_type: Type of installation, must be InstallationType type.
147 subkey: Subkey to look up. It must be a ChromeRegistryValues type.
148
149 Returns:
150 True if the key exists, otherwise False.
151 """
152 key = self._GetRegistryType(install_type)
153 key_name = self._GetKeyName(install_type, subkey)
154 try:
155 hkey = _winreg.OpenKey(key, key_name)
156 except _winreg.error:
157 return False
158 if not hkey.handle:
159 return False
160 hkey.Close()
161 return True
162
163 def GetKeyValue(self, install_type, subkey):
164 """Gets value of the specified subkey from the registry.
165
166 Args:
167 install_type: Type of installation, must be InstallationType type.
168 subkey: ChromeRegistryValue type representing the value to be returned.
169
170 Returns:
171 A string representing the subkey value.
172 """
173 reg_value = ''
174 key = self._GetRegistryType(install_type)
175 key_name = self._GetKeyName(install_type, subkey)
176 hkey = _winreg.OpenKey(key, key_name)
177 if hkey.handle:
178 reg_value = str(_winreg.QueryValueEx(hkey, subkey)[0])
179 hkey.Close()
180 return reg_value
181
182 def DeleteRegistryEntries(self, install_type):
183 """Deletes chrome registry settings.
184
185 Args:
186 install_type: Type of installation, must be InstallationType type.
187 """
188 reg_type = self._GetRegistryType(install_type)
189 key_name = self._GetKeyName(install_type,
190 ChromeRegistryValues.UNINSTALL_ARGUMENTS)
191 root = key_name[:key_name.rfind('\\')]
192 child = key_name[key_name.rfind('\\') + 1:]
193 key = _winreg.OpenKey(reg_type, root, 0, _winreg.KEY_ALL_ACCESS)
194 _winreg.DeleteKey(key, child)
195 key.Close()
196
197
198 class ChromeInstallation(object):
199 """Provides pertinent information about the installed Chrome version.
200
201 The type of Chrome version must be passed as an argument to the constructor,
202 (i.e. - user or system level).
203 """
204
205 _CSIDL_COMMON_APPDATA = 0x1C
206 _CSIDL_PROGRAM_FILESX86 = 0x2A
207
208 def __init__(self, install_type):
209 assert(install_type == InstallationType.SYSTEM or
210 install_type == InstallationType.USER)
211 self._type = install_type
212 self._regedit = ChromeRegistryKeys()
213
214 def _GetWinLocalFolder(self, ftype=_CSIDL_COMMON_APPDATA):
215 """Returns full path of the 'Local' folder on Windows.
216
217 Args:
218 ftype: Location to look up, which could vary based on installation type.
219
220 Returns:
221 A String representing the folder path if successful, otherwise an empty
222 string.
223 """
224 SHGetFolderPathW = windll.shell32.SHGetFolderPathW
225 SHGetFolderPathW.argtypes = [wintypes.HWND,
226 ctypes.c_int,
227 wintypes.HANDLE,
228 wintypes.DWORD,
229 wintypes.LPCWSTR]
230 path_buf = wintypes.create_unicode_buffer(wintypes.MAX_PATH)
231 result = SHGetFolderPathW(0, ftype, 0, 0, path_buf)
232 return str(path_buf.value)
233
234 def _GetUninstallString(self):
235 """Returns the Chrome uninstall string from the registry."""
236 return self._regedit.GetKeyValue(self._type,
237 ChromeRegistryValues.UNINSTALL_STRING)
238
239 def _GetUninstallArguments(self):
240 """Returns the Chrome uninstall arguments from the registry."""
241 return self._regedit.GetKeyValue(self._type,
242 ChromeRegistryValues.UNINSTALL_ARGUMENTS)
243
244 def GetExePath(self):
245 """Returns Chrome binary location based on installation type.
246
247 Currently this method only returns the location of the Chrome binary.
248 It does not support Chromium.
249 """
250 if self._type == InstallationType.USER:
251 folder_id = self._CSIDL_COMMON_APPDATA
252 elif self._type == InstallationType.SYSTEM:
253 folder_id = self._CSIDL_PROGRAM_FILESX86
254 chrome_path = os.path.join(self._GetWinLocalFolder(folder_id), 'Google',
255 'Chrome', 'Application', 'chrome.exe')
256 return (chrome_path if os.path.exists(chrome_path) else '')
257
258 @staticmethod
259 def GetCurrent():
260 """Determines Chrome installation type.
261
262 Returns:
263 ChromeInstallation object if Chrome is present, otherwise None.
264 """
265 registry = ChromeRegistryKeys()
266 if registry.DoesKeyExist(InstallationType.SYSTEM,
267 ChromeRegistryValues.PRODUCT_VERSION):
268 return ChromeInstallation(InstallationType.SYSTEM)
269 elif registry.DoesKeyExist(InstallationType.USER,
270 ChromeRegistryValues.PRODUCT_VERSION):
271 return ChromeInstallation(InstallationType.USER)
272 return None
273
274 def Uninstall(self):
275 """Uninstalls Chrome."""
276 chrome_path = self.GetExePath()
277 reg_opts = self._GetUninstallArguments()
278 uninstall_str = self._GetUninstallString()
279 options = '%s --force-uninstall' % (reg_opts)
280 if self._type == InstallationType.SYSTEM:
281 options += ' --system-level'
282 if not os.path.exists(chrome_path):
283 raise RuntimeError('Could not find chrome, aborting uninstall.')
284 logging.info('Launching Chrome installer...')
285 cmd = '"%s" %s' % (uninstall_str, options)
286 subprocess.call(cmd)
287 if not os.path.exists(chrome_path):
288 logging.info('Chrome was uninstalled successfully...')
289 logging.info('Deleting registry entries...')
290 self._regedit.DeleteRegistryEntries(self._type)
291 logging.info('Uninstall complete.')
292 else:
293 raise RuntimeError('Uninstall failed.')
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698