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

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

Powered by Google App Engine
This is Rietveld 408576698