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

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

Powered by Google App Engine
This is Rietveld 408576698