OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <windows.h> | 5 #include <windows.h> |
6 #include <msi.h> | 6 #include <msi.h> |
7 #include <shellapi.h> | 7 #include <shellapi.h> |
8 #include <shlobj.h> | 8 #include <shlobj.h> |
9 | 9 |
10 #include <string> | 10 #include <string> |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 #include "chrome/installer/util/util_constants.h" | 43 #include "chrome/installer/util/util_constants.h" |
44 | 44 |
45 #include "installer_util_strings.h" // NOLINT | 45 #include "installer_util_strings.h" // NOLINT |
46 | 46 |
47 using installer::Product; | 47 using installer::Product; |
48 using installer::ProductPackageMapping; | 48 using installer::ProductPackageMapping; |
49 using installer::Products; | 49 using installer::Products; |
50 using installer::Package; | 50 using installer::Package; |
51 using installer::Packages; | 51 using installer::Packages; |
52 using installer::Version; | 52 using installer::Version; |
53 using installer::MasterPreferences; | 53 using installer_util::MasterPreferences; |
54 | 54 |
55 namespace { | 55 namespace { |
56 | 56 |
57 // This method unpacks and uncompresses the given archive file. For Chrome | 57 // This method unpacks and uncompresses the given archive file. For Chrome |
58 // install we are creating a uncompressed archive that contains all the files | 58 // install we are creating a uncompressed archive that contains all the files |
59 // needed for the installer. This uncompressed archive is later compressed. | 59 // needed for the installer. This uncompressed archive is later compressed. |
60 // | 60 // |
61 // This method first uncompresses archive specified by parameter "archive" | 61 // This method first uncompresses archive specified by parameter "archive" |
62 // and assumes that it will result in an uncompressed full archive file | 62 // and assumes that it will result in an uncompressed full archive file |
63 // (chrome.7z) or uncompressed archive patch file (chrome_patch.diff). If it | 63 // (chrome.7z) or uncompressed archive patch file (chrome_patch.diff). If it |
64 // is patch file, it is applied to the old archive file that should be | 64 // is patch file, it is applied to the old archive file that should be |
65 // present on the system already. As the final step the new archive file | 65 // present on the system already. As the final step the new archive file |
66 // is unpacked in the path specified by parameter "output_directory". | 66 // is unpacked in the path specified by parameter "output_directory". |
67 DWORD UnPackArchive(const FilePath& archive, | 67 DWORD UnPackArchive(const FilePath& archive, |
68 const Package& installation, | 68 const Package& installation, |
69 const FilePath& temp_path, | 69 const FilePath& temp_path, |
70 const FilePath& output_directory, | 70 const FilePath& output_directory, |
71 bool& incremental_install) { | 71 bool& incremental_install) { |
72 // First uncompress the payload. This could be a differential | 72 // First uncompress the payload. This could be a differential |
73 // update (patch.7z) or full archive (chrome.7z). If this uncompress fails | 73 // update (patch.7z) or full archive (chrome.7z). If this uncompress fails |
74 // return with error. | 74 // return with error. |
75 std::wstring unpacked_file; | 75 std::wstring unpacked_file; |
76 int32 ret = LzmaUtil::UnPackArchive(archive.value(), temp_path.value(), | 76 int32 ret = LzmaUtil::UnPackArchive(archive.value(), temp_path.value(), |
77 &unpacked_file); | 77 &unpacked_file); |
78 if (ret != NO_ERROR) | 78 if (ret != NO_ERROR) |
79 return ret; | 79 return ret; |
80 | 80 |
81 FilePath uncompressed_archive(temp_path.Append(installer::kChromeArchive)); | 81 FilePath uncompressed_archive(temp_path.Append(installer::kChromeArchive)); |
82 scoped_ptr<Version> archive_version( | 82 scoped_ptr<Version> archive_version( |
83 installer::GetVersionFromArchiveDir(installation.path())); | 83 setup_util::GetVersionFromArchiveDir(installation.path())); |
84 | 84 |
85 // Check if this is differential update and if it is, patch it to the | 85 // Check if this is differential update and if it is, patch it to the |
86 // installer archive that should already be on the machine. We assume | 86 // installer archive that should already be on the machine. We assume |
87 // it is a differential installer if chrome.7z is not found. | 87 // it is a differential installer if chrome.7z is not found. |
88 if (!file_util::PathExists(uncompressed_archive)) { | 88 if (!file_util::PathExists(uncompressed_archive)) { |
89 incremental_install = true; | 89 incremental_install = true; |
90 VLOG(1) << "Differential patch found. Applying to existing archive."; | 90 VLOG(1) << "Differential patch found. Applying to existing archive."; |
91 if (!archive_version.get()) { | 91 if (!archive_version.get()) { |
92 LOG(ERROR) << "Can not use differential update when Chrome is not " | 92 LOG(ERROR) << "Can not use differential update when Chrome is not " |
93 << "installed on the system."; | 93 << "installed on the system."; |
94 return installer::CHROME_NOT_INSTALLED; | 94 return installer_util::CHROME_NOT_INSTALLED; |
95 } | 95 } |
96 | 96 |
97 FilePath existing_archive( | 97 FilePath existing_archive( |
98 installation.path().Append(archive_version->GetString())); | 98 installation.path().Append(archive_version->GetString())); |
99 existing_archive = existing_archive.Append(installer::kInstallerDir); | 99 existing_archive = existing_archive.Append(installer_util::kInstallerDir); |
100 existing_archive = existing_archive.Append(installer::kChromeArchive); | 100 existing_archive = existing_archive.Append(installer::kChromeArchive); |
101 if (int i = installer::ApplyDiffPatch(FilePath(existing_archive), | 101 if (int i = setup_util::ApplyDiffPatch(FilePath(existing_archive), |
102 FilePath(unpacked_file), | 102 FilePath(unpacked_file), |
103 FilePath(uncompressed_archive))) { | 103 FilePath(uncompressed_archive))) { |
104 LOG(ERROR) << "Binary patching failed with error " << i; | 104 LOG(ERROR) << "Binary patching failed with error " << i; |
105 return i; | 105 return i; |
106 } | 106 } |
107 } | 107 } |
108 | 108 |
109 // Unpack the uncompressed archive. | 109 // Unpack the uncompressed archive. |
110 return LzmaUtil::UnPackArchive(uncompressed_archive.value(), | 110 return LzmaUtil::UnPackArchive(uncompressed_archive.value(), |
111 output_directory.value(), &unpacked_file); | 111 output_directory.value(), &unpacked_file); |
112 } | 112 } |
113 | 113 |
114 | 114 |
115 // This function is called when --rename-chrome-exe option is specified on | 115 // This function is called when --rename-chrome-exe option is specified on |
116 // setup.exe command line. This function assumes an in-use update has happened | 116 // setup.exe command line. This function assumes an in-use update has happened |
117 // for Chrome so there should be a file called new_chrome.exe on the file | 117 // for Chrome so there should be a file called new_chrome.exe on the file |
118 // system and a key called 'opv' in the registry. This function will move | 118 // system and a key called 'opv' in the registry. This function will move |
119 // new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. | 119 // new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. |
120 installer::InstallStatus RenameChromeExecutables( | 120 installer_util::InstallStatus RenameChromeExecutables( |
121 const Package& installation) { | 121 const Package& installation) { |
122 FilePath chrome_exe(installation.path().Append(installer::kChromeExe)); | 122 FilePath chrome_exe(installation.path().Append(installer_util::kChromeExe)); |
123 FilePath chrome_old_exe(installation.path().Append( | 123 FilePath chrome_old_exe(installation.path().Append( |
124 installer::kChromeOldExe)); | 124 installer_util::kChromeOldExe)); |
125 FilePath chrome_new_exe(installation.path().Append( | 125 FilePath chrome_new_exe(installation.path().Append( |
126 installer::kChromeNewExe)); | 126 installer_util::kChromeNewExe)); |
127 | 127 |
128 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); | 128 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
129 install_list->AddDeleteTreeWorkItem(chrome_old_exe); | 129 install_list->AddDeleteTreeWorkItem(chrome_old_exe); |
130 FilePath temp_path; | 130 FilePath temp_path; |
131 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { | 131 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { |
132 LOG(ERROR) << "Failed to create Temp directory " << temp_path.value(); | 132 LOG(ERROR) << "Failed to create Temp directory " << temp_path.value(); |
133 return installer::RENAME_FAILED; | 133 return installer_util::RENAME_FAILED; |
134 } | 134 } |
135 | 135 |
136 install_list->AddCopyTreeWorkItem(chrome_new_exe.value(), | 136 install_list->AddCopyTreeWorkItem(chrome_new_exe.value(), |
137 chrome_exe.value(), | 137 chrome_exe.value(), |
138 temp_path.ToWStringHack(), | 138 temp_path.ToWStringHack(), |
139 WorkItem::IF_DIFFERENT, | 139 WorkItem::IF_DIFFERENT, |
140 std::wstring()); | 140 std::wstring()); |
141 install_list->AddDeleteTreeWorkItem(chrome_new_exe); | 141 install_list->AddDeleteTreeWorkItem(chrome_new_exe); |
142 | 142 |
143 HKEY reg_root = installation.system_level() ? HKEY_LOCAL_MACHINE : | 143 HKEY reg_root = installation.system_level() ? HKEY_LOCAL_MACHINE : |
144 HKEY_CURRENT_USER; | 144 HKEY_CURRENT_USER; |
145 const Products& products = installation.products(); | 145 const Products& products = installation.products(); |
146 for (size_t i = 0; i < products.size(); ++i) { | 146 for (size_t i = 0; i < products.size(); ++i) { |
147 const Product* product = products[i]; | 147 const Product* product = products[i]; |
148 BrowserDistribution* browser_dist = product->distribution(); | 148 BrowserDistribution* browser_dist = product->distribution(); |
149 std::wstring version_key(browser_dist->GetVersionKey()); | 149 std::wstring version_key(browser_dist->GetVersionKey()); |
150 install_list->AddDeleteRegValueWorkItem(reg_root, | 150 install_list->AddDeleteRegValueWorkItem(reg_root, |
151 version_key, | 151 version_key, |
152 google_update::kRegOldVersionField, | 152 google_update::kRegOldVersionField, |
153 true); | 153 true); |
154 install_list->AddDeleteRegValueWorkItem(reg_root, | 154 install_list->AddDeleteRegValueWorkItem(reg_root, |
155 version_key, | 155 version_key, |
156 google_update::kRegRenameCmdField, | 156 google_update::kRegRenameCmdField, |
157 true); | 157 true); |
158 } | 158 } |
159 installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; | 159 installer_util::InstallStatus ret = installer_util::RENAME_SUCCESSFUL; |
160 if (!install_list->Do()) { | 160 if (!install_list->Do()) { |
161 LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; | 161 LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; |
162 install_list->Rollback(); | 162 install_list->Rollback(); |
163 ret = installer::RENAME_FAILED; | 163 ret = installer_util::RENAME_FAILED; |
164 } | 164 } |
165 file_util::Delete(temp_path, true); | 165 file_util::Delete(temp_path, true); |
166 return ret; | 166 return ret; |
167 } | 167 } |
168 | 168 |
169 bool CheckPreInstallConditions(const Package& installation, | 169 bool CheckPreInstallConditions(const Package& installation, |
170 installer::InstallStatus& status) { | 170 installer_util::InstallStatus& status) { |
171 const Products& products = installation.products(); | 171 const Products& products = installation.products(); |
172 DCHECK(products.size()); | 172 DCHECK(products.size()); |
173 | 173 |
174 bool is_first_install = true; | 174 bool is_first_install = true; |
175 | 175 |
176 for (size_t i = 0; i < products.size(); ++i) { | 176 for (size_t i = 0; i < products.size(); ++i) { |
177 const Product* product = products[i]; | 177 const Product* product = products[i]; |
178 BrowserDistribution* browser_dist = product->distribution(); | 178 BrowserDistribution* browser_dist = product->distribution(); |
179 scoped_ptr<Version> installed_version(product->GetInstalledVersion()); | 179 scoped_ptr<Version> installed_version(product->GetInstalledVersion()); |
180 // TODO(tommi): If the current install is for a different distribution than | 180 // TODO(tommi): If the current install is for a different distribution than |
181 // that might already be installed, then this check is incorrect. | 181 // that might already be installed, then this check is incorrect. |
182 if (installed_version.get()) | 182 if (installed_version.get()) |
183 is_first_install = false; | 183 is_first_install = false; |
184 | 184 |
185 // Check to avoid simultaneous per-user and per-machine installs. | 185 // Check to avoid simultaneous per-user and per-machine installs. |
186 scoped_ptr<Version> chrome_version( | 186 scoped_ptr<Version> chrome_version( |
187 InstallUtil::GetChromeVersion(browser_dist, !product->system_level())); | 187 InstallUtil::GetChromeVersion(browser_dist, !product->system_level())); |
188 | 188 |
189 if (chrome_version.get()) { | 189 if (chrome_version.get()) { |
190 LOG(ERROR) << "Already installed version " << chrome_version->GetString() | 190 LOG(ERROR) << "Already installed version " << chrome_version->GetString() |
191 << " conflicts with the current install mode."; | 191 << " conflicts with the current install mode."; |
192 if (!product->system_level() && is_first_install) { | 192 if (!product->system_level() && is_first_install) { |
193 // This is user-level install and there is a system-level chrome | 193 // This is user-level install and there is a system-level chrome |
194 // installation. Instruct Omaha to launch the existing one. There | 194 // installation. Instruct Omaha to launch the existing one. There |
195 // should be no error dialog. | 195 // should be no error dialog. |
196 FilePath chrome_exe(installer::GetChromeInstallPath( | 196 FilePath chrome_exe(installer::GetChromeInstallPath( |
197 !product->system_level(), browser_dist)); | 197 !product->system_level(), browser_dist)); |
198 if (chrome_exe.empty()) { | 198 if (chrome_exe.empty()) { |
199 // If we failed to construct install path. Give up. | 199 // If we failed to construct install path. Give up. |
200 status = installer::OS_ERROR; | 200 status = installer_util::OS_ERROR; |
201 product->WriteInstallerResult(status, IDS_INSTALL_OS_ERROR_BASE, | 201 product->WriteInstallerResult(status, IDS_INSTALL_OS_ERROR_BASE, |
202 NULL); | 202 NULL); |
203 } else { | 203 } else { |
204 status = installer::EXISTING_VERSION_LAUNCHED; | 204 status = installer_util::EXISTING_VERSION_LAUNCHED; |
205 chrome_exe = chrome_exe.Append(installer::kChromeExe); | 205 chrome_exe = chrome_exe.Append(installer_util::kChromeExe); |
206 CommandLine cmd(chrome_exe); | 206 CommandLine cmd(chrome_exe); |
207 cmd.AppendSwitch(switches::kFirstRun); | 207 cmd.AppendSwitch(switches::kFirstRun); |
208 product->WriteInstallerResult(status, 0, NULL); | 208 product->WriteInstallerResult(status, 0, NULL); |
209 VLOG(1) << "Launching existing system-level chrome instead."; | 209 VLOG(1) << "Launching existing system-level chrome instead."; |
210 base::LaunchApp(cmd, false, false, NULL); | 210 base::LaunchApp(cmd, false, false, NULL); |
211 } | 211 } |
212 return false; | 212 return false; |
213 } | 213 } |
214 | 214 |
215 // If the following compile assert fires it means that the InstallStatus | 215 // If the following compile assert fires it means that the InstallStatus |
216 // enumeration changed which will break the contract between the old | 216 // enumeration changed which will break the contract between the old |
217 // chrome installed and the new setup.exe that is trying to upgrade. | 217 // chrome installed and the new setup.exe that is trying to upgrade. |
218 COMPILE_ASSERT(installer::SXS_OPTION_NOT_SUPPORTED == 33, | 218 COMPILE_ASSERT(installer_util::SXS_OPTION_NOT_SUPPORTED == 33, |
219 dont_change_enum); | 219 dont_change_enum); |
220 | 220 |
221 // This is an update, not an install. Omaha should know the difference | 221 // This is an update, not an install. Omaha should know the difference |
222 // and not show a dialog. | 222 // and not show a dialog. |
223 status = product->system_level() ? | 223 status = product->system_level() ? |
224 installer::USER_LEVEL_INSTALL_EXISTS : | 224 installer_util::USER_LEVEL_INSTALL_EXISTS : |
225 installer::SYSTEM_LEVEL_INSTALL_EXISTS; | 225 installer_util::SYSTEM_LEVEL_INSTALL_EXISTS; |
226 int str_id = product->system_level() ? | 226 int str_id = product->system_level() ? |
227 IDS_INSTALL_USER_LEVEL_EXISTS_BASE : | 227 IDS_INSTALL_USER_LEVEL_EXISTS_BASE : |
228 IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE; | 228 IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE; |
229 product->WriteInstallerResult(status, str_id, NULL); | 229 product->WriteInstallerResult(status, str_id, NULL); |
230 return false; | 230 return false; |
231 } | 231 } |
232 } | 232 } |
233 | 233 |
234 // If no previous installation of Chrome, make sure installation directory | 234 // If no previous installation of Chrome, make sure installation directory |
235 // either does not exist or can be deleted (i.e. is not locked by some other | 235 // either does not exist or can be deleted (i.e. is not locked by some other |
236 // process). | 236 // process). |
237 if (is_first_install) { | 237 if (is_first_install) { |
238 if (file_util::PathExists(installation.path()) && | 238 if (file_util::PathExists(installation.path()) && |
239 !file_util::Delete(installation.path(), true)) { | 239 !file_util::Delete(installation.path(), true)) { |
240 LOG(ERROR) << "Installation directory " << installation.path().value() | 240 LOG(ERROR) << "Installation directory " << installation.path().value() |
241 << " exists and can not be deleted."; | 241 << " exists and can not be deleted."; |
242 status = installer::INSTALL_DIR_IN_USE; | 242 status = installer_util::INSTALL_DIR_IN_USE; |
243 int str_id = IDS_INSTALL_DIR_IN_USE_BASE; | 243 int str_id = IDS_INSTALL_DIR_IN_USE_BASE; |
244 WriteInstallerResult(products, status, str_id, NULL); | 244 WriteInstallerResult(products, status, str_id, NULL); |
245 return false; | 245 return false; |
246 } | 246 } |
247 } | 247 } |
248 | 248 |
249 return true; | 249 return true; |
250 } | 250 } |
251 | 251 |
252 installer::InstallStatus InstallChrome(const CommandLine& cmd_line, | 252 installer_util::InstallStatus InstallChrome(const CommandLine& cmd_line, |
253 const Package& installation, const MasterPreferences& prefs) { | 253 const Package& installation, const MasterPreferences& prefs) { |
254 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | 254 installer_util::InstallStatus install_status = installer_util::UNKNOWN_STATUS; |
255 if (!CheckPreInstallConditions(installation, install_status)) | 255 if (!CheckPreInstallConditions(installation, install_status)) |
256 return install_status; | 256 return install_status; |
257 | 257 |
258 // For install the default location for chrome.packed.7z is in current | 258 // For install the default location for chrome.packed.7z is in current |
259 // folder, so get that value first. | 259 // folder, so get that value first. |
260 FilePath archive(cmd_line.GetProgram().DirName().Append( | 260 FilePath archive(cmd_line.GetProgram().DirName().Append( |
261 installer::kChromeCompressedArchive)); | 261 installer::kChromeCompressedArchive)); |
262 | 262 |
263 // If --install-archive is given, get the user specified value | 263 // If --install-archive is given, get the user specified value |
264 if (cmd_line.HasSwitch(installer::switches::kInstallArchive)) { | 264 if (cmd_line.HasSwitch(installer_util::switches::kInstallArchive)) { |
265 archive = cmd_line.GetSwitchValuePath( | 265 archive = cmd_line.GetSwitchValuePath( |
266 installer::switches::kInstallArchive); | 266 installer_util::switches::kInstallArchive); |
267 } | 267 } |
268 VLOG(1) << "Archive found to install Chrome " << archive.value(); | 268 VLOG(1) << "Archive found to install Chrome " << archive.value(); |
269 bool system_level = installation.system_level(); | 269 bool system_level = installation.system_level(); |
270 const Products& products = installation.products(); | 270 const Products& products = installation.products(); |
271 | 271 |
272 // Create a temp folder where we will unpack Chrome archive. If it fails, | 272 // Create a temp folder where we will unpack Chrome archive. If it fails, |
273 // then we are doomed, so return immediately and no cleanup is required. | 273 // then we are doomed, so return immediately and no cleanup is required. |
274 FilePath temp_path; | 274 FilePath temp_path; |
275 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { | 275 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { |
276 LOG(ERROR) << "Could not create temporary path."; | 276 LOG(ERROR) << "Could not create temporary path."; |
277 WriteInstallerResult(products, installer::TEMP_DIR_FAILED, | 277 WriteInstallerResult(products, installer_util::TEMP_DIR_FAILED, |
278 IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL); | 278 IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL); |
279 return installer::TEMP_DIR_FAILED; | 279 return installer_util::TEMP_DIR_FAILED; |
280 } | 280 } |
281 VLOG(1) << "created path " << temp_path.value(); | 281 VLOG(1) << "created path " << temp_path.value(); |
282 | 282 |
283 FilePath unpack_path(temp_path.Append(installer::kInstallSourceDir)); | 283 FilePath unpack_path(temp_path.Append(installer::kInstallSourceDir)); |
284 bool incremental_install = false; | 284 bool incremental_install = false; |
285 if (UnPackArchive(archive, installation, temp_path, unpack_path, | 285 if (UnPackArchive(archive, installation, temp_path, unpack_path, |
286 incremental_install)) { | 286 incremental_install)) { |
287 install_status = installer::UNCOMPRESSION_FAILED; | 287 install_status = installer_util::UNCOMPRESSION_FAILED; |
288 WriteInstallerResult(products, install_status, | 288 WriteInstallerResult(products, install_status, |
289 IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, NULL); | 289 IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, NULL); |
290 } else { | 290 } else { |
291 VLOG(1) << "unpacked to " << unpack_path.value(); | 291 VLOG(1) << "unpacked to " << unpack_path.value(); |
292 FilePath src_path(unpack_path.Append(installer::kInstallSourceChromeDir)); | 292 FilePath src_path(unpack_path.Append(installer::kInstallSourceChromeDir)); |
293 scoped_ptr<Version> | 293 scoped_ptr<Version> |
294 installer_version(installer::GetVersionFromArchiveDir(src_path)); | 294 installer_version(setup_util::GetVersionFromArchiveDir(src_path)); |
295 if (!installer_version.get()) { | 295 if (!installer_version.get()) { |
296 LOG(ERROR) << "Did not find any valid version in installer."; | 296 LOG(ERROR) << "Did not find any valid version in installer."; |
297 install_status = installer::INVALID_ARCHIVE; | 297 install_status = installer_util::INVALID_ARCHIVE; |
298 WriteInstallerResult(products, install_status, | 298 WriteInstallerResult(products, install_status, |
299 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); | 299 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); |
300 } else { | 300 } else { |
301 // TODO(tommi): Move towards having only a single version that is common | 301 // TODO(tommi): Move towards having only a single version that is common |
302 // to all products. Only the package should have a version since it | 302 // to all products. Only the package should have a version since it |
303 // represents all the binaries. When a single product is upgraded, all | 303 // represents all the binaries. When a single product is upgraded, all |
304 // currently installed product for the shared binary installation, should | 304 // currently installed product for the shared binary installation, should |
305 // (or rather must) be upgraded. | 305 // (or rather must) be upgraded. |
306 VLOG(1) << "version to install: " << installer_version->GetString(); | 306 VLOG(1) << "version to install: " << installer_version->GetString(); |
307 bool higher_version_installed = false; | 307 bool higher_version_installed = false; |
308 for (size_t i = 0; i < installation.products().size(); ++i) { | 308 for (size_t i = 0; i < installation.products().size(); ++i) { |
309 const Product* product = installation.products()[i]; | 309 const Product* product = installation.products()[i]; |
310 scoped_ptr<Version> v(product->GetInstalledVersion()); | 310 scoped_ptr<Version> v(product->GetInstalledVersion()); |
311 if (v.get() && v->IsHigherThan(installer_version.get())) { | 311 if (v.get() && v->IsHigherThan(installer_version.get())) { |
312 LOG(ERROR) << "Higher version is already installed."; | 312 LOG(ERROR) << "Higher version is already installed."; |
313 higher_version_installed = true; | 313 higher_version_installed = true; |
314 install_status = installer::HIGHER_VERSION_EXISTS; | 314 install_status = installer_util::HIGHER_VERSION_EXISTS; |
315 | 315 |
316 if (product->distribution()->GetType() != | 316 if (product->distribution()->GetType() != |
317 BrowserDistribution::CHROME_BROWSER) { | 317 BrowserDistribution::CHROME_BROWSER) { |
318 // TODO(robertshield): We should take the installer result text | 318 // TODO(robertshield): We should take the installer result text |
319 // strings from the Product. | 319 // strings from the Product. |
320 product->WriteInstallerResult(install_status, | 320 product->WriteInstallerResult(install_status, |
321 IDS_INSTALL_HIGHER_VERSION_BASE, NULL); | 321 IDS_INSTALL_HIGHER_VERSION_BASE, NULL); |
322 } else { | 322 } else { |
323 product->WriteInstallerResult(install_status, | 323 product->WriteInstallerResult(install_status, |
324 IDS_INSTALL_HIGHER_VERSION_CF_BASE, NULL); | 324 IDS_INSTALL_HIGHER_VERSION_CF_BASE, NULL); |
325 } | 325 } |
326 } | 326 } |
327 } | 327 } |
328 | 328 |
329 if (!higher_version_installed) { | 329 if (!higher_version_installed) { |
330 // We want to keep uncompressed archive (chrome.7z) that we get after | 330 // We want to keep uncompressed archive (chrome.7z) that we get after |
331 // uncompressing and binary patching. Get the location for this file. | 331 // uncompressing and binary patching. Get the location for this file. |
332 FilePath archive_to_copy(temp_path.Append(installer::kChromeArchive)); | 332 FilePath archive_to_copy(temp_path.Append(installer::kChromeArchive)); |
333 FilePath prefs_source_path(cmd_line.GetSwitchValueNative( | 333 FilePath prefs_source_path(cmd_line.GetSwitchValueNative( |
334 installer::switches::kInstallerData)); | 334 installer_util::switches::kInstallerData)); |
335 install_status = installer::InstallOrUpdateChrome(cmd_line.GetProgram(), | 335 install_status = installer::InstallOrUpdateChrome(cmd_line.GetProgram(), |
336 archive_to_copy, temp_path, prefs_source_path, prefs, | 336 archive_to_copy, temp_path, prefs_source_path, prefs, |
337 *installer_version, installation); | 337 *installer_version, installation); |
338 | 338 |
339 int install_msg_base = IDS_INSTALL_FAILED_BASE; | 339 int install_msg_base = IDS_INSTALL_FAILED_BASE; |
340 std::wstring chrome_exe; | 340 std::wstring chrome_exe; |
341 if (install_status == installer::SAME_VERSION_REPAIR_FAILED) { | 341 if (install_status == installer_util::SAME_VERSION_REPAIR_FAILED) { |
342 if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) { | 342 if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) { |
343 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE; | 343 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE; |
344 } else { | 344 } else { |
345 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE; | 345 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE; |
346 } | 346 } |
347 } else if (install_status != installer::INSTALL_FAILED) { | 347 } else if (install_status != installer_util::INSTALL_FAILED) { |
348 if (installation.path().empty()) { | 348 if (installation.path().empty()) { |
349 // If we failed to construct install path, it means the OS call to | 349 // If we failed to construct install path, it means the OS call to |
350 // get %ProgramFiles% or %AppData% failed. Report this as failure. | 350 // get %ProgramFiles% or %AppData% failed. Report this as failure. |
351 install_msg_base = IDS_INSTALL_OS_ERROR_BASE; | 351 install_msg_base = IDS_INSTALL_OS_ERROR_BASE; |
352 install_status = installer::OS_ERROR; | 352 install_status = installer_util::OS_ERROR; |
353 } else { | 353 } else { |
354 chrome_exe = installation.path() | 354 chrome_exe = installation.path() |
355 .Append(installer::kChromeExe).value(); | 355 .Append(installer_util::kChromeExe).value(); |
356 chrome_exe = L"\"" + chrome_exe + L"\""; | 356 chrome_exe = L"\"" + chrome_exe + L"\""; |
357 install_msg_base = 0; | 357 install_msg_base = 0; |
358 } | 358 } |
359 } | 359 } |
360 | 360 |
361 const Product* chrome_install = | 361 const Product* chrome_install = |
362 FindProduct(products, BrowserDistribution::CHROME_BROWSER); | 362 FindProduct(products, BrowserDistribution::CHROME_BROWSER); |
363 | 363 |
364 bool value = false; | 364 bool value = false; |
365 if (chrome_install) { | 365 if (chrome_install) { |
366 prefs.GetBool( | 366 prefs.GetBool( |
367 installer::master_preferences::kDoNotRegisterForUpdateLaunch, | 367 installer_util::master_preferences::kDoNotRegisterForUpdateLaunch, |
368 &value); | 368 &value); |
369 } else { | 369 } else { |
370 value = true; // Never register. | 370 value = true; // Never register. |
371 } | 371 } |
372 | 372 |
373 bool write_chrome_launch_string = (!value) && | 373 bool write_chrome_launch_string = (!value) && |
374 (install_status != installer::IN_USE_UPDATED); | 374 (install_status != installer_util::IN_USE_UPDATED); |
375 | 375 |
376 WriteInstallerResult(products, install_status, | 376 WriteInstallerResult(products, install_status, |
377 install_msg_base, write_chrome_launch_string ? &chrome_exe : NULL); | 377 install_msg_base, write_chrome_launch_string ? &chrome_exe : NULL); |
378 | 378 |
379 if (install_status == installer::FIRST_INSTALL_SUCCESS) { | 379 if (install_status == installer_util::FIRST_INSTALL_SUCCESS) { |
380 VLOG(1) << "First install successful."; | 380 VLOG(1) << "First install successful."; |
381 if (chrome_install) { | 381 if (chrome_install) { |
382 // We never want to launch Chrome in system level install mode. | 382 // We never want to launch Chrome in system level install mode. |
383 bool do_not_launch_chrome = false; | 383 bool do_not_launch_chrome = false; |
384 prefs.GetBool( | 384 prefs.GetBool( |
385 installer::master_preferences::kDoNotLaunchChrome, | 385 installer_util::master_preferences::kDoNotLaunchChrome, |
386 &do_not_launch_chrome); | 386 &do_not_launch_chrome); |
387 if (!chrome_install->system_level() && !do_not_launch_chrome) | 387 if (!chrome_install->system_level() && !do_not_launch_chrome) |
388 chrome_install->LaunchChrome(); | 388 chrome_install->LaunchChrome(); |
389 } | 389 } |
390 } else if ((install_status == installer::NEW_VERSION_UPDATED) || | 390 } else if ((install_status == installer_util::NEW_VERSION_UPDATED) || |
391 (install_status == installer::IN_USE_UPDATED)) { | 391 (install_status == installer_util::IN_USE_UPDATED)) { |
392 for (size_t i = 0; i < products.size(); ++i) { | 392 for (size_t i = 0; i < products.size(); ++i) { |
393 installer::RemoveLegacyRegistryKeys( | 393 installer::RemoveLegacyRegistryKeys( |
394 products[i]->distribution()); | 394 products[i]->distribution()); |
395 } | 395 } |
396 } | 396 } |
397 } | 397 } |
398 } | 398 } |
399 // There might be an experiment (for upgrade usually) that needs to happen. | 399 // There might be an experiment (for upgrade usually) that needs to happen. |
400 // An experiment's outcome can include chrome's uninstallation. If that is | 400 // An experiment's outcome can include chrome's uninstallation. If that is |
401 // the case we would not do that directly at this point but in another | 401 // the case we would not do that directly at this point but in another |
402 // instance of setup.exe | 402 // instance of setup.exe |
403 // | 403 // |
404 // There is another way to reach this same function if this is a system | 404 // There is another way to reach this same function if this is a system |
405 // level install. See HandleNonInstallCmdLineOptions(). | 405 // level install. See HandleNonInstallCmdLineOptions(). |
406 for (size_t i = 0; i < products.size(); ++i) { | 406 for (size_t i = 0; i < products.size(); ++i) { |
407 const Product* product = products[i]; | 407 const Product* product = products[i]; |
408 product->distribution()->LaunchUserExperiment(install_status, | 408 product->distribution()->LaunchUserExperiment(install_status, |
409 *installer_version, *product, product->system_level()); | 409 *installer_version, *product, product->system_level()); |
410 } | 410 } |
411 } | 411 } |
412 | 412 |
413 // Delete temporary files. These include install temporary directory | 413 // Delete temporary files. These include install temporary directory |
414 // and master profile file if present. Note that we do not care about rollback | 414 // and master profile file if present. Note that we do not care about rollback |
415 // here and we schedule for deletion on reboot below if the deletes fail. As | 415 // here and we schedule for deletion on reboot below if the deletes fail. As |
416 // such, we do not use DeleteTreeWorkItem. | 416 // such, we do not use DeleteTreeWorkItem. |
417 VLOG(1) << "Deleting temporary directory " << temp_path.value(); | 417 VLOG(1) << "Deleting temporary directory " << temp_path.value(); |
418 bool cleanup_success = file_util::Delete(temp_path, true); | 418 bool cleanup_success = file_util::Delete(temp_path, true); |
419 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { | 419 if (cmd_line.HasSwitch(installer_util::switches::kInstallerData)) { |
420 std::wstring prefs_path = cmd_line.GetSwitchValueNative( | 420 std::wstring prefs_path = cmd_line.GetSwitchValueNative( |
421 installer::switches::kInstallerData); | 421 installer_util::switches::kInstallerData); |
422 cleanup_success = file_util::Delete(prefs_path, true) && cleanup_success; | 422 cleanup_success = file_util::Delete(prefs_path, true) && cleanup_success; |
423 } | 423 } |
424 | 424 |
425 // The above cleanup has been observed to fail on several users machines. | 425 // The above cleanup has been observed to fail on several users machines. |
426 // Specifically, it appears that the temp folder may be locked when we try | 426 // Specifically, it appears that the temp folder may be locked when we try |
427 // to delete it. This is Rather Bad in the case where we have failed updates | 427 // to delete it. This is Rather Bad in the case where we have failed updates |
428 // as we end up filling users' disks with large-ish temp files. To mitigate | 428 // as we end up filling users' disks with large-ish temp files. To mitigate |
429 // this, if we fail to delete the temp folders, then schedule them for | 429 // this, if we fail to delete the temp folders, then schedule them for |
430 // deletion at next reboot. | 430 // deletion at next reboot. |
431 if (!cleanup_success) { | 431 if (!cleanup_success) { |
432 ScheduleDirectoryForDeletion(temp_path.ToWStringHack().c_str()); | 432 ScheduleDirectoryForDeletion(temp_path.ToWStringHack().c_str()); |
433 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { | 433 if (cmd_line.HasSwitch(installer_util::switches::kInstallerData)) { |
434 std::wstring prefs_path = cmd_line.GetSwitchValueNative( | 434 std::wstring prefs_path = cmd_line.GetSwitchValueNative( |
435 installer::switches::kInstallerData); | 435 installer_util::switches::kInstallerData); |
436 ScheduleDirectoryForDeletion(prefs_path.c_str()); | 436 ScheduleDirectoryForDeletion(prefs_path.c_str()); |
437 } | 437 } |
438 } | 438 } |
439 | 439 |
440 for (size_t i = 0; i < products.size(); ++i) { | 440 for (size_t i = 0; i < products.size(); ++i) { |
441 const Product* product = products[i]; | 441 const Product* product = products[i]; |
442 product->distribution()->UpdateDiffInstallStatus(system_level, | 442 product->distribution()->UpdateDiffInstallStatus(system_level, |
443 incremental_install, install_status); | 443 incremental_install, install_status); |
444 } | 444 } |
445 | 445 |
446 return install_status; | 446 return install_status; |
447 } | 447 } |
448 | 448 |
449 installer::InstallStatus UninstallChrome(const CommandLine& cmd_line, | 449 installer_util::InstallStatus UninstallChrome(const CommandLine& cmd_line, |
450 const Product& product) { | 450 const Product& product) { |
451 VLOG(1) << "Uninstalling Chome"; | 451 VLOG(1) << "Uninstalling Chome"; |
452 | 452 |
453 scoped_ptr<Version> installed_version(product.GetInstalledVersion()); | 453 scoped_ptr<Version> installed_version(product.GetInstalledVersion()); |
454 if (installed_version.get()) | 454 if (installed_version.get()) |
455 VLOG(1) << "version on the system: " << installed_version->GetString(); | 455 VLOG(1) << "version on the system: " << installed_version->GetString(); |
456 | 456 |
457 bool force = cmd_line.HasSwitch(installer::switches::kForceUninstall); | 457 bool force = cmd_line.HasSwitch(installer_util::switches::kForceUninstall); |
458 if (!installed_version.get() && !force) { | 458 if (!installed_version.get() && !force) { |
459 LOG(ERROR) << "No Chrome installation found for uninstall."; | 459 LOG(ERROR) << "No Chrome installation found for uninstall."; |
460 product.WriteInstallerResult(installer::CHROME_NOT_INSTALLED, | 460 product.WriteInstallerResult(installer_util::CHROME_NOT_INSTALLED, |
461 IDS_UNINSTALL_FAILED_BASE, NULL); | 461 IDS_UNINSTALL_FAILED_BASE, NULL); |
462 return installer::CHROME_NOT_INSTALLED; | 462 return installer_util::CHROME_NOT_INSTALLED; |
463 } | 463 } |
464 | 464 |
465 bool remove_all = !cmd_line.HasSwitch( | 465 bool remove_all = !cmd_line.HasSwitch( |
466 installer::switches::kDoNotRemoveSharedItems); | 466 installer_util::switches::kDoNotRemoveSharedItems); |
467 | 467 |
468 return installer::UninstallChrome(cmd_line.GetProgram(), product, remove_all, | 468 return installer::UninstallChrome(cmd_line.GetProgram(), product, remove_all, |
469 force, cmd_line); | 469 force, cmd_line); |
470 } | 470 } |
471 | 471 |
472 installer::InstallStatus ShowEULADialog(const std::wstring& inner_frame) { | 472 installer_util::InstallStatus ShowEULADialog(const std::wstring& inner_frame) { |
473 VLOG(1) << "About to show EULA"; | 473 VLOG(1) << "About to show EULA"; |
474 std::wstring eula_path = installer::GetLocalizedEulaResource(); | 474 std::wstring eula_path = installer_util::GetLocalizedEulaResource(); |
475 if (eula_path.empty()) { | 475 if (eula_path.empty()) { |
476 LOG(ERROR) << "No EULA path available"; | 476 LOG(ERROR) << "No EULA path available"; |
477 return installer::EULA_REJECTED; | 477 return installer_util::EULA_REJECTED; |
478 } | 478 } |
479 // Newer versions of the caller pass an inner frame parameter that must | 479 // Newer versions of the caller pass an inner frame parameter that must |
480 // be given to the html page being launched. | 480 // be given to the html page being launched. |
481 if (!inner_frame.empty()) { | 481 if (!inner_frame.empty()) { |
482 eula_path += L"?innerframe="; | 482 eula_path += L"?innerframe="; |
483 eula_path += inner_frame; | 483 eula_path += inner_frame; |
484 } | 484 } |
485 installer::EulaHTMLDialog dlg(eula_path); | 485 installer::EulaHTMLDialog dlg(eula_path); |
486 installer::EulaHTMLDialog::Outcome outcome = dlg.ShowModal(); | 486 installer::EulaHTMLDialog::Outcome outcome = dlg.ShowModal(); |
487 if (installer::EulaHTMLDialog::REJECTED == outcome) { | 487 if (installer::EulaHTMLDialog::REJECTED == outcome) { |
488 LOG(ERROR) << "EULA rejected or EULA failure"; | 488 LOG(ERROR) << "EULA rejected or EULA failure"; |
489 return installer::EULA_REJECTED; | 489 return installer_util::EULA_REJECTED; |
490 } | 490 } |
491 if (installer::EulaHTMLDialog::ACCEPTED_OPT_IN == outcome) { | 491 if (installer::EulaHTMLDialog::ACCEPTED_OPT_IN == outcome) { |
492 VLOG(1) << "EULA accepted (opt-in)"; | 492 VLOG(1) << "EULA accepted (opt-in)"; |
493 return installer::EULA_ACCEPTED_OPT_IN; | 493 return installer_util::EULA_ACCEPTED_OPT_IN; |
494 } | 494 } |
495 VLOG(1) << "EULA accepted (no opt-in)"; | 495 VLOG(1) << "EULA accepted (no opt-in)"; |
496 return installer::EULA_ACCEPTED; | 496 return installer_util::EULA_ACCEPTED; |
497 } | 497 } |
498 | 498 |
499 // This method processes any command line options that make setup.exe do | 499 // This method processes any command line options that make setup.exe do |
500 // various tasks other than installation (renaming chrome.exe, showing eula | 500 // various tasks other than installation (renaming chrome.exe, showing eula |
501 // among others). This function returns true if any such command line option | 501 // among others). This function returns true if any such command line option |
502 // has been found and processed (so setup.exe should exit at that point). | 502 // has been found and processed (so setup.exe should exit at that point). |
503 bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line, | 503 bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line, |
504 int& exit_code, | 504 int& exit_code, |
505 const ProductPackageMapping& installs) { | 505 const ProductPackageMapping& installs) { |
506 DCHECK(installs.products().size()); | 506 DCHECK(installs.products().size()); |
507 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { | 507 if (cmd_line.HasSwitch(installer_util::switches::kUpdateSetupExe)) { |
508 installer::InstallStatus status = installer::SETUP_PATCH_FAILED; | 508 installer_util::InstallStatus status = installer_util::SETUP_PATCH_FAILED; |
509 // If --update-setup-exe command line option is given, we apply the given | 509 // If --update-setup-exe command line option is given, we apply the given |
510 // patch to current exe, and store the resulting binary in the path | 510 // patch to current exe, and store the resulting binary in the path |
511 // specified by --new-setup-exe. But we need to first unpack the file | 511 // specified by --new-setup-exe. But we need to first unpack the file |
512 // given in --update-setup-exe. | 512 // given in --update-setup-exe. |
513 FilePath temp_path; | 513 FilePath temp_path; |
514 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { | 514 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { |
515 LOG(ERROR) << "Could not create temporary path."; | 515 LOG(ERROR) << "Could not create temporary path."; |
516 } else { | 516 } else { |
517 std::wstring setup_patch = cmd_line.GetSwitchValueNative( | 517 std::wstring setup_patch = cmd_line.GetSwitchValueNative( |
518 installer::switches::kUpdateSetupExe); | 518 installer_util::switches::kUpdateSetupExe); |
519 VLOG(1) << "Opening archive " << setup_patch; | 519 VLOG(1) << "Opening archive " << setup_patch; |
520 std::wstring uncompressed_patch; | 520 std::wstring uncompressed_patch; |
521 if (LzmaUtil::UnPackArchive(setup_patch, temp_path.ToWStringHack(), | 521 if (LzmaUtil::UnPackArchive(setup_patch, temp_path.ToWStringHack(), |
522 &uncompressed_patch) == NO_ERROR) { | 522 &uncompressed_patch) == NO_ERROR) { |
523 FilePath old_setup_exe = cmd_line.GetProgram(); | 523 FilePath old_setup_exe = cmd_line.GetProgram(); |
524 FilePath new_setup_exe = cmd_line.GetSwitchValuePath( | 524 FilePath new_setup_exe = cmd_line.GetSwitchValuePath( |
525 installer::switches::kNewSetupExe); | 525 installer_util::switches::kNewSetupExe); |
526 if (!installer::ApplyDiffPatch(old_setup_exe, | 526 if (!setup_util::ApplyDiffPatch(old_setup_exe, |
527 FilePath(uncompressed_patch), | 527 FilePath(uncompressed_patch), |
528 new_setup_exe)) | 528 new_setup_exe)) |
529 status = installer::NEW_VERSION_UPDATED; | 529 status = installer_util::NEW_VERSION_UPDATED; |
530 } | 530 } |
531 } | 531 } |
532 | 532 |
533 exit_code = BrowserDistribution::GetInstallReturnCode(status); | 533 exit_code = BrowserDistribution::GetInstallReturnCode(status); |
534 if (exit_code) { | 534 if (exit_code) { |
535 LOG(WARNING) << "setup.exe patching failed."; | 535 LOG(WARNING) << "setup.exe patching failed."; |
536 WriteInstallerResult(installs.products(), status, | 536 WriteInstallerResult(installs.products(), status, |
537 IDS_SETUP_PATCH_FAILED_BASE, NULL); | 537 IDS_SETUP_PATCH_FAILED_BASE, NULL); |
538 } | 538 } |
539 file_util::Delete(temp_path, true); | 539 file_util::Delete(temp_path, true); |
540 return true; | 540 return true; |
541 } else if (cmd_line.HasSwitch(installer::switches::kShowEula)) { | 541 } else if (cmd_line.HasSwitch(installer_util::switches::kShowEula)) { |
542 // Check if we need to show the EULA. If it is passed as a command line | 542 // Check if we need to show the EULA. If it is passed as a command line |
543 // then the dialog is shown and regardless of the outcome setup exits here. | 543 // then the dialog is shown and regardless of the outcome setup exits here. |
544 std::wstring inner_frame = | 544 std::wstring inner_frame = |
545 cmd_line.GetSwitchValueNative(installer::switches::kShowEula); | 545 cmd_line.GetSwitchValueNative(installer_util::switches::kShowEula); |
546 exit_code = ShowEULADialog(inner_frame); | 546 exit_code = ShowEULADialog(inner_frame); |
547 if (installer::EULA_REJECTED != exit_code) | 547 if (installer_util::EULA_REJECTED != exit_code) |
548 GoogleUpdateSettings::SetEULAConsent(true); | 548 GoogleUpdateSettings::SetEULAConsent(true); |
549 return true; | 549 return true; |
550 } else if (cmd_line.HasSwitch( | 550 } else if (cmd_line.HasSwitch( |
551 installer::switches::kRegisterChromeBrowser)) { | 551 installer_util::switches::kRegisterChromeBrowser)) { |
552 const Product* chrome_install = | 552 const Product* chrome_install = |
553 FindProduct(installs.products(), BrowserDistribution::CHROME_BROWSER); | 553 FindProduct(installs.products(), BrowserDistribution::CHROME_BROWSER); |
554 DCHECK(chrome_install); | 554 DCHECK(chrome_install); |
555 if (chrome_install) { | 555 if (chrome_install) { |
556 // If --register-chrome-browser option is specified, register all | 556 // If --register-chrome-browser option is specified, register all |
557 // Chrome protocol/file associations as well as register it as a valid | 557 // Chrome protocol/file associations as well as register it as a valid |
558 // browser for Start Menu->Internet shortcut. This option should only | 558 // browser for Start Menu->Internet shortcut. This option should only |
559 // be used when setup.exe is launched with admin rights. We do not | 559 // be used when setup.exe is launched with admin rights. We do not |
560 // make any user specific changes in this option. | 560 // make any user specific changes in this option. |
561 std::wstring chrome_exe(cmd_line.GetSwitchValueNative( | 561 std::wstring chrome_exe(cmd_line.GetSwitchValueNative( |
562 installer::switches::kRegisterChromeBrowser)); | 562 installer_util::switches::kRegisterChromeBrowser)); |
563 std::wstring suffix; | 563 std::wstring suffix; |
564 if (cmd_line.HasSwitch( | 564 if (cmd_line.HasSwitch( |
565 installer::switches::kRegisterChromeBrowserSuffix)) { | 565 installer_util::switches::kRegisterChromeBrowserSuffix)) { |
566 suffix = cmd_line.GetSwitchValueNative( | 566 suffix = cmd_line.GetSwitchValueNative( |
567 installer::switches::kRegisterChromeBrowserSuffix); | 567 installer_util::switches::kRegisterChromeBrowserSuffix); |
568 } | 568 } |
569 exit_code = ShellUtil::RegisterChromeBrowser( | 569 exit_code = ShellUtil::RegisterChromeBrowser( |
570 chrome_install->distribution(), chrome_exe, suffix, false); | 570 chrome_install->distribution(), chrome_exe, suffix, false); |
571 } else { | 571 } else { |
572 LOG(ERROR) << "Can't register browser - Chrome distribution not found"; | 572 LOG(ERROR) << "Can't register browser - Chrome distribution not found"; |
573 exit_code = installer::UNKNOWN_STATUS; | 573 exit_code = installer_util::UNKNOWN_STATUS; |
574 } | 574 } |
575 return true; | 575 return true; |
576 } else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { | 576 } else if (cmd_line.HasSwitch(installer_util::switches::kRenameChromeExe)) { |
577 // If --rename-chrome-exe is specified, we want to rename the executables | 577 // If --rename-chrome-exe is specified, we want to rename the executables |
578 // and exit. | 578 // and exit. |
579 const Packages& packages = installs.packages(); | 579 const Packages& packages = installs.packages(); |
580 DCHECK_EQ(1U, packages.size()); | 580 DCHECK_EQ(1U, packages.size()); |
581 for (size_t i = 0; i < packages.size(); ++i) | 581 for (size_t i = 0; i < packages.size(); ++i) |
582 exit_code = RenameChromeExecutables(*packages[i].get()); | 582 exit_code = RenameChromeExecutables(*packages[i].get()); |
583 return true; | 583 return true; |
584 } else if (cmd_line.HasSwitch( | 584 } else if (cmd_line.HasSwitch( |
585 installer::switches::kRemoveChromeRegistration)) { | 585 installer_util::switches::kRemoveChromeRegistration)) { |
586 // This is almost reverse of --register-chrome-browser option above. | 586 // This is almost reverse of --register-chrome-browser option above. |
587 // Here we delete Chrome browser registration. This option should only | 587 // Here we delete Chrome browser registration. This option should only |
588 // be used when setup.exe is launched with admin rights. We do not | 588 // be used when setup.exe is launched with admin rights. We do not |
589 // make any user specific changes in this option. | 589 // make any user specific changes in this option. |
590 std::wstring suffix; | 590 std::wstring suffix; |
591 if (cmd_line.HasSwitch( | 591 if (cmd_line.HasSwitch( |
592 installer::switches::kRegisterChromeBrowserSuffix)) { | 592 installer_util::switches::kRegisterChromeBrowserSuffix)) { |
593 suffix = cmd_line.GetSwitchValueNative( | 593 suffix = cmd_line.GetSwitchValueNative( |
594 installer::switches::kRegisterChromeBrowserSuffix); | 594 installer_util::switches::kRegisterChromeBrowserSuffix); |
595 } | 595 } |
596 installer::InstallStatus tmp = installer::UNKNOWN_STATUS; | 596 installer_util::InstallStatus tmp = installer_util::UNKNOWN_STATUS; |
597 const Product* chrome_install = | 597 const Product* chrome_install = |
598 FindProduct(installs.products(), BrowserDistribution::CHROME_BROWSER); | 598 FindProduct(installs.products(), BrowserDistribution::CHROME_BROWSER); |
599 DCHECK(chrome_install); | 599 DCHECK(chrome_install); |
600 if (chrome_install) { | 600 if (chrome_install) { |
601 installer::DeleteChromeRegistrationKeys(chrome_install->distribution(), | 601 installer::DeleteChromeRegistrationKeys(chrome_install->distribution(), |
602 HKEY_LOCAL_MACHINE, suffix, tmp); | 602 HKEY_LOCAL_MACHINE, suffix, tmp); |
603 } | 603 } |
604 exit_code = tmp; | 604 exit_code = tmp; |
605 return true; | 605 return true; |
606 } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) { | 606 } else if (cmd_line.HasSwitch(installer_util::switches::kInactiveUserToast)) { |
607 // Launch the inactive user toast experiment. | 607 // Launch the inactive user toast experiment. |
608 int flavor = -1; | 608 int flavor = -1; |
609 base::StringToInt(cmd_line.GetSwitchValueNative( | 609 base::StringToInt(cmd_line.GetSwitchValueNative( |
610 installer::switches::kInactiveUserToast), &flavor); | 610 installer_util::switches::kInactiveUserToast), &flavor); |
611 DCHECK_NE(-1, flavor); | 611 DCHECK_NE(-1, flavor); |
612 if (flavor == -1) { | 612 if (flavor == -1) { |
613 exit_code = installer::UNKNOWN_STATUS; | 613 exit_code = installer_util::UNKNOWN_STATUS; |
614 } else { | 614 } else { |
615 const Products& products = installs.products(); | 615 const Products& products = installs.products(); |
616 for (size_t i = 0; i < products.size(); ++i) { | 616 for (size_t i = 0; i < products.size(); ++i) { |
617 const Product* product = products[i]; | 617 const Product* product = products[i]; |
618 BrowserDistribution* browser_dist = product->distribution(); | 618 BrowserDistribution* browser_dist = product->distribution(); |
619 browser_dist->InactiveUserToastExperiment(flavor, *product); | 619 browser_dist->InactiveUserToastExperiment(flavor, *product); |
620 } | 620 } |
621 } | 621 } |
622 return true; | 622 return true; |
623 } else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { | 623 } else if (cmd_line.HasSwitch(installer_util::switches::kSystemLevelToast)) { |
624 const Products& products = installs.products(); | 624 const Products& products = installs.products(); |
625 for (size_t i = 0; i < products.size(); ++i) { | 625 for (size_t i = 0; i < products.size(); ++i) { |
626 const Product* product = products[i]; | 626 const Product* product = products[i]; |
627 BrowserDistribution* browser_dist = product->distribution(); | 627 BrowserDistribution* browser_dist = product->distribution(); |
628 // We started as system-level and have been re-launched as user level | 628 // We started as system-level and have been re-launched as user level |
629 // to continue with the toast experiment. | 629 // to continue with the toast experiment. |
630 scoped_ptr<Version> installed_version( | 630 scoped_ptr<Version> installed_version( |
631 InstallUtil::GetChromeVersion(browser_dist, installs.system_level())); | 631 InstallUtil::GetChromeVersion(browser_dist, installs.system_level())); |
632 browser_dist->LaunchUserExperiment(installer::REENTRY_SYS_UPDATE, | 632 browser_dist->LaunchUserExperiment(installer_util::REENTRY_SYS_UPDATE, |
633 *installed_version, *product, true); | 633 *installed_version, *product, true); |
634 } | 634 } |
635 return true; | 635 return true; |
636 } | 636 } |
637 return false; | 637 return false; |
638 } | 638 } |
639 | 639 |
640 bool ShowRebootDialog() { | 640 bool ShowRebootDialog() { |
641 // Get a token for this process. | 641 // Get a token for this process. |
642 HANDLE token; | 642 HANDLE token; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 | 707 |
708 } // namespace | 708 } // namespace |
709 | 709 |
710 int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, | 710 int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, |
711 wchar_t* command_line, int show_command) { | 711 wchar_t* command_line, int show_command) { |
712 // The exit manager is in charge of calling the dtors of singletons. | 712 // The exit manager is in charge of calling the dtors of singletons. |
713 base::AtExitManager exit_manager; | 713 base::AtExitManager exit_manager; |
714 CommandLine::Init(0, NULL); | 714 CommandLine::Init(0, NULL); |
715 | 715 |
716 const MasterPreferences& prefs = | 716 const MasterPreferences& prefs = |
717 installer::MasterPreferences::ForCurrentProcess(); | 717 installer_util::MasterPreferences::ForCurrentProcess(); |
718 installer::InitInstallerLogging(prefs); | 718 installer::InitInstallerLogging(prefs); |
719 | 719 |
720 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); | 720 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); |
721 VLOG(1) << "Command Line: " << cmd_line.command_line_string(); | 721 VLOG(1) << "Command Line: " << cmd_line.command_line_string(); |
722 | 722 |
723 bool system_install = false; | 723 bool system_install = false; |
724 prefs.GetBool(installer::master_preferences::kSystemLevel, | 724 prefs.GetBool(installer_util::master_preferences::kSystemLevel, |
725 &system_install); | 725 &system_install); |
726 VLOG(1) << "system install is " << system_install; | 726 VLOG(1) << "system install is " << system_install; |
727 | 727 |
728 ProductPackageMapping installations(system_install); | 728 ProductPackageMapping installations(system_install); |
729 PopulateInstallations(prefs, &installations); | 729 PopulateInstallations(prefs, &installations); |
730 | 730 |
731 // Check to make sure current system is WinXP or later. If not, log | 731 // Check to make sure current system is WinXP or later. If not, log |
732 // error message and get out. | 732 // error message and get out. |
733 if (!InstallUtil::IsOSSupported()) { | 733 if (!InstallUtil::IsOSSupported()) { |
734 LOG(ERROR) << "Chrome only supports Windows XP or later."; | 734 LOG(ERROR) << "Chrome only supports Windows XP or later."; |
735 WriteInstallerResult(installations.products(), | 735 WriteInstallerResult(installations.products(), |
736 installer::OS_NOT_SUPPORTED, IDS_INSTALL_OS_NOT_SUPPORTED_BASE, | 736 installer_util::OS_NOT_SUPPORTED, IDS_INSTALL_OS_NOT_SUPPORTED_BASE, |
737 NULL); | 737 NULL); |
738 return installer::OS_NOT_SUPPORTED; | 738 return installer_util::OS_NOT_SUPPORTED; |
739 } | 739 } |
740 | 740 |
741 // Initialize COM for use later. | 741 // Initialize COM for use later. |
742 AutoCom auto_com; | 742 AutoCom auto_com; |
743 if (!auto_com.Init(system_install)) { | 743 if (!auto_com.Init(system_install)) { |
744 WriteInstallerResult(installations.products(), | 744 WriteInstallerResult(installations.products(), |
745 installer::OS_ERROR, IDS_INSTALL_OS_ERROR_BASE, NULL); | 745 installer_util::OS_ERROR, IDS_INSTALL_OS_ERROR_BASE, NULL); |
746 return installer::OS_ERROR; | 746 return installer_util::OS_ERROR; |
747 } | 747 } |
748 | 748 |
749 // Some command line options don't work with SxS install/uninstall | 749 // Some command line options don't work with SxS install/uninstall |
750 if (InstallUtil::IsChromeSxSProcess()) { | 750 if (InstallUtil::IsChromeSxSProcess()) { |
751 if (system_install || | 751 if (system_install || |
752 cmd_line.HasSwitch(installer::switches::kForceUninstall) || | 752 cmd_line.HasSwitch(installer_util::switches::kForceUninstall) || |
753 cmd_line.HasSwitch(installer::switches::kMakeChromeDefault) || | 753 cmd_line.HasSwitch(installer_util::switches::kMakeChromeDefault) || |
754 cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser) || | 754 cmd_line.HasSwitch(installer_util::switches::kRegisterChromeBrowser) || |
755 cmd_line.HasSwitch( | 755 cmd_line.HasSwitch( |
756 installer::switches::kRemoveChromeRegistration) || | 756 installer_util::switches::kRemoveChromeRegistration) || |
757 cmd_line.HasSwitch(installer::switches::kInactiveUserToast) || | 757 cmd_line.HasSwitch(installer_util::switches::kInactiveUserToast) || |
758 cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { | 758 cmd_line.HasSwitch(installer_util::switches::kSystemLevelToast)) { |
759 return installer::SXS_OPTION_NOT_SUPPORTED; | 759 return installer_util::SXS_OPTION_NOT_SUPPORTED; |
760 } | 760 } |
761 } | 761 } |
762 | 762 |
763 int exit_code = 0; | 763 int exit_code = 0; |
764 if (HandleNonInstallCmdLineOptions(cmd_line, exit_code, installations)) | 764 if (HandleNonInstallCmdLineOptions(cmd_line, exit_code, installations)) |
765 return exit_code; | 765 return exit_code; |
766 | 766 |
767 if (system_install && !IsUserAnAdmin()) { | 767 if (system_install && !IsUserAnAdmin()) { |
768 if (base::win::GetVersion() >= base::win::VERSION_VISTA && | 768 if (base::win::GetVersion() >= base::win::VERSION_VISTA && |
769 !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { | 769 !cmd_line.HasSwitch(installer_util::switches::kRunAsAdmin)) { |
770 CommandLine new_cmd(CommandLine::NO_PROGRAM); | 770 CommandLine new_cmd(CommandLine::NO_PROGRAM); |
771 new_cmd.AppendArguments(cmd_line, true); | 771 new_cmd.AppendArguments(cmd_line, true); |
772 // Append --run-as-admin flag to let the new instance of setup.exe know | 772 // Append --run-as-admin flag to let the new instance of setup.exe know |
773 // that we already tried to launch ourselves as admin. | 773 // that we already tried to launch ourselves as admin. |
774 new_cmd.AppendSwitch(installer::switches::kRunAsAdmin); | 774 new_cmd.AppendSwitch(installer_util::switches::kRunAsAdmin); |
775 DWORD exit_code = installer::UNKNOWN_STATUS; | 775 DWORD exit_code = installer_util::UNKNOWN_STATUS; |
776 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); | 776 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); |
777 return exit_code; | 777 return exit_code; |
778 } else { | 778 } else { |
779 LOG(ERROR) << "Non admin user can not install system level Chrome."; | 779 LOG(ERROR) << "Non admin user can not install system level Chrome."; |
780 WriteInstallerResult(installations.products(), | 780 WriteInstallerResult(installations.products(), |
781 installer::INSUFFICIENT_RIGHTS, | 781 installer_util::INSUFFICIENT_RIGHTS, |
782 IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE, NULL); | 782 IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE, NULL); |
783 return installer::INSUFFICIENT_RIGHTS; | 783 return installer_util::INSUFFICIENT_RIGHTS; |
784 } | 784 } |
785 } | 785 } |
786 | 786 |
787 bool is_uninstall = cmd_line.HasSwitch(installer::switches::kUninstall); | 787 bool is_uninstall = cmd_line.HasSwitch(installer_util::switches::kUninstall); |
788 | 788 |
789 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | 789 installer_util::InstallStatus install_status = installer_util::UNKNOWN_STATUS; |
790 // If --uninstall option is given, uninstall chrome | 790 // If --uninstall option is given, uninstall chrome |
791 if (is_uninstall) { | 791 if (is_uninstall) { |
792 DCHECK_EQ(1U, installations.products().size()) << | 792 DCHECK_EQ(1U, installations.products().size()) << |
793 "We currently really only support uninstalling one distribution " | 793 "We currently really only support uninstalling one distribution " |
794 "at a time"; | 794 "at a time"; |
795 for (size_t i = 0; i < installations.products().size(); ++i) { | 795 for (size_t i = 0; i < installations.products().size(); ++i) { |
796 install_status = UninstallChrome(cmd_line, | 796 install_status = UninstallChrome(cmd_line, |
797 *installations.products()[i]); | 797 *installations.products()[i]); |
798 } | 798 } |
799 } else { | 799 } else { |
800 // If --uninstall option is not specified, we assume it is install case. | 800 // If --uninstall option is not specified, we assume it is install case. |
801 const Packages& packages = installations.packages(); | 801 const Packages& packages = installations.packages(); |
802 VLOG(1) << "Installing to " << packages.size() << " target paths"; | 802 VLOG(1) << "Installing to " << packages.size() << " target paths"; |
803 for (size_t i = 0; i < packages.size(); ++i) { | 803 for (size_t i = 0; i < packages.size(); ++i) { |
804 install_status = InstallChrome(cmd_line, *packages[i].get(), prefs); | 804 install_status = InstallChrome(cmd_line, *packages[i].get(), prefs); |
805 } | 805 } |
806 } | 806 } |
807 | 807 |
808 const Product* cf_install = | 808 const Product* cf_install = |
809 FindProduct(installations.products(), BrowserDistribution::CHROME_FRAME); | 809 FindProduct(installations.products(), BrowserDistribution::CHROME_FRAME); |
810 | 810 |
811 if (cf_install && | 811 if (cf_install && |
812 !cmd_line.HasSwitch(installer::switches::kForceUninstall)) { | 812 !cmd_line.HasSwitch(installer_util::switches::kForceUninstall)) { |
813 if (install_status == installer::UNINSTALL_REQUIRES_REBOOT) { | 813 if (install_status == installer_util::UNINSTALL_REQUIRES_REBOOT) { |
814 ShowRebootDialog(); | 814 ShowRebootDialog(); |
815 } else if (is_uninstall) { | 815 } else if (is_uninstall) { |
816 ::MessageBoxW(NULL, | 816 ::MessageBoxW(NULL, |
817 installer::GetLocalizedString( | 817 installer_util::GetLocalizedString( |
818 IDS_UNINSTALL_COMPLETE_BASE).c_str(), | 818 IDS_UNINSTALL_COMPLETE_BASE).c_str(), |
819 cf_install->distribution()->GetApplicationName().c_str(), | 819 cf_install->distribution()->GetApplicationName().c_str(), |
820 MB_OK); | 820 MB_OK); |
821 } | 821 } |
822 } | 822 } |
823 | 823 |
824 int return_code = 0; | 824 int return_code = 0; |
825 // MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will | 825 // MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will |
826 // rollback the action. If we're uninstalling we want to avoid this, so always | 826 // rollback the action. If we're uninstalling we want to avoid this, so always |
827 // report success, squashing any more informative return codes. | 827 // report success, squashing any more informative return codes. |
828 // TODO(tommi): Fix this loop when IsMsi has been moved out of the Product | 828 // TODO(tommi): Fix this loop when IsMsi has been moved out of the Product |
829 // class. | 829 // class. |
830 for (size_t i = 0; i < installations.products().size(); ++i) { | 830 for (size_t i = 0; i < installations.products().size(); ++i) { |
831 const Product* product = installations.products()[i]; | 831 const Product* product = installations.products()[i]; |
832 if (!(product->IsMsi() && is_uninstall)) { | 832 if (!(product->IsMsi() && is_uninstall)) { |
833 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT | 833 // Note that we allow the status installer_util::UNINSTALL_REQUIRES_REBOOT |
834 // to pass through, since this is only returned on uninstall which is | 834 // to pass through, since this is only returned on uninstall which is |
835 // never invoked directly by Google Update. | 835 // never invoked directly by Google Update. |
836 return_code = BrowserDistribution::GetInstallReturnCode(install_status); | 836 return_code = BrowserDistribution::GetInstallReturnCode(install_status); |
837 } | 837 } |
838 } | 838 } |
839 | 839 |
840 VLOG(1) << "Installation complete, returning: " << return_code; | 840 VLOG(1) << "Installation complete, returning: " << return_code; |
841 | 841 |
842 return return_code; | 842 return return_code; |
843 } | 843 } |
OLD | NEW |