OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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> |
11 | 11 |
12 #include "base/at_exit.h" | 12 #include "base/at_exit.h" |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
15 #include "base/file_util.h" | 15 #include "base/file_util.h" |
16 #include "base/file_version_info.h" | 16 #include "base/file_version_info.h" |
17 #include "base/path_service.h" | 17 #include "base/path_service.h" |
18 #include "base/process_util.h" | 18 #include "base/process_util.h" |
19 #include "base/string_number_conversions.h" | 19 #include "base/string_number_conversions.h" |
20 #include "base/string_util.h" | 20 #include "base/string_util.h" |
21 #include "base/utf_string_conversions.h" | 21 #include "base/utf_string_conversions.h" |
22 #include "base/values.h" | 22 #include "base/values.h" |
23 #include "base/win/registry.h" | |
23 #include "base/win/scoped_handle.h" | 24 #include "base/win/scoped_handle.h" |
24 #include "base/win/win_util.h" | 25 #include "base/win/win_util.h" |
25 #include "base/win/windows_version.h" | 26 #include "base/win/windows_version.h" |
26 #include "breakpad/src/client/windows/handler/exception_handler.h" | 27 #include "breakpad/src/client/windows/handler/exception_handler.h" |
27 #include "chrome/common/chrome_switches.h" | 28 #include "chrome/common/chrome_switches.h" |
28 #include "chrome/installer/setup/chrome_frame_ready_mode.h" | 29 #include "chrome/installer/setup/chrome_frame_ready_mode.h" |
29 #include "chrome/installer/setup/install.h" | 30 #include "chrome/installer/setup/install.h" |
30 #include "chrome/installer/setup/setup_constants.h" | 31 #include "chrome/installer/setup/setup_constants.h" |
31 #include "chrome/installer/setup/setup_util.h" | 32 #include "chrome/installer/setup/setup_util.h" |
32 #include "chrome/installer/setup/uninstall.h" | 33 #include "chrome/installer/setup/uninstall.h" |
33 #include "chrome/installer/util/browser_distribution.h" | 34 #include "chrome/installer/util/browser_distribution.h" |
35 #include "chrome/installer/util/channel_info.h" | |
34 #include "chrome/installer/util/delete_after_reboot_helper.h" | 36 #include "chrome/installer/util/delete_after_reboot_helper.h" |
35 #include "chrome/installer/util/delete_tree_work_item.h" | 37 #include "chrome/installer/util/delete_tree_work_item.h" |
36 #include "chrome/installer/util/google_update_settings.h" | 38 #include "chrome/installer/util/google_update_settings.h" |
37 #include "chrome/installer/util/google_update_constants.h" | 39 #include "chrome/installer/util/google_update_constants.h" |
38 #include "chrome/installer/util/helper.h" | 40 #include "chrome/installer/util/helper.h" |
39 #include "chrome/installer/util/html_dialog.h" | 41 #include "chrome/installer/util/html_dialog.h" |
40 #include "chrome/installer/util/install_util.h" | 42 #include "chrome/installer/util/install_util.h" |
41 #include "chrome/installer/util/installer_state.h" | 43 #include "chrome/installer/util/installer_state.h" |
42 #include "chrome/installer/util/installation_state.h" | 44 #include "chrome/installer/util/installation_state.h" |
43 #include "chrome/installer/util/l10n_string_util.h" | 45 #include "chrome/installer/util/l10n_string_util.h" |
44 #include "chrome/installer/util/logging_installer.h" | 46 #include "chrome/installer/util/logging_installer.h" |
45 #include "chrome/installer/util/lzma_util.h" | 47 #include "chrome/installer/util/lzma_util.h" |
46 #include "chrome/installer/util/master_preferences.h" | 48 #include "chrome/installer/util/master_preferences.h" |
47 #include "chrome/installer/util/master_preferences_constants.h" | 49 #include "chrome/installer/util/master_preferences_constants.h" |
48 #include "chrome/installer/util/package_properties.h" | |
49 #include "chrome/installer/util/shell_util.h" | 50 #include "chrome/installer/util/shell_util.h" |
50 #include "chrome/installer/util/util_constants.h" | 51 #include "chrome/installer/util/util_constants.h" |
51 | 52 |
52 #include "installer_util_strings.h" // NOLINT | 53 #include "installer_util_strings.h" // NOLINT |
53 | 54 |
54 using installer::InstallerState; | 55 using installer::InstallerState; |
55 using installer::InstallationState; | 56 using installer::InstallationState; |
56 using installer::Product; | 57 using installer::Product; |
57 using installer::ProductPackageMapping; | |
58 using installer::ProductState; | 58 using installer::ProductState; |
59 using installer::Products; | 59 using installer::Products; |
60 using installer::Package; | |
61 using installer::Packages; | |
62 using installer::MasterPreferences; | 60 using installer::MasterPreferences; |
63 | 61 |
64 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; | 62 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; |
65 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; | 63 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; |
66 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; | 64 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; |
67 | 65 |
68 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( | 66 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( |
69 MiniDumpWithProcessThreadData | // Get PEB and TEB. | 67 MiniDumpWithProcessThreadData | // Get PEB and TEB. |
70 MiniDumpWithUnloadedModules | // Get unloaded modules when available. | 68 MiniDumpWithUnloadedModules | // Get unloaded modules when available. |
71 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack. | 69 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack. |
72 | 70 |
73 namespace { | 71 namespace { |
74 | 72 |
75 // This method unpacks and uncompresses the given archive file. For Chrome | 73 // This method unpacks and uncompresses the given archive file. For Chrome |
76 // install we are creating a uncompressed archive that contains all the files | 74 // install we are creating a uncompressed archive that contains all the files |
77 // needed for the installer. This uncompressed archive is later compressed. | 75 // needed for the installer. This uncompressed archive is later compressed. |
78 // | 76 // |
79 // This method first uncompresses archive specified by parameter "archive" | 77 // This method first uncompresses archive specified by parameter "archive" |
80 // and assumes that it will result in an uncompressed full archive file | 78 // and assumes that it will result in an uncompressed full archive file |
81 // (chrome.7z) or uncompressed archive patch file (chrome_patch.diff). If it | 79 // (chrome.7z) or uncompressed archive patch file (chrome_patch.diff). If it |
82 // is patch file, it is applied to the old archive file that should be | 80 // is patch file, it is applied to the old archive file that should be |
83 // present on the system already. As the final step the new archive file | 81 // present on the system already. As the final step the new archive file |
84 // is unpacked in the path specified by parameter "output_directory". | 82 // is unpacked in the path specified by parameter "output_directory". |
85 DWORD UnPackArchive(const FilePath& archive, | 83 DWORD UnPackArchive(const FilePath& archive, |
86 const Package& installation, | 84 const InstallerState& installer_state, |
87 const FilePath& temp_path, | 85 const FilePath& temp_path, |
88 const FilePath& output_directory, | 86 const FilePath& output_directory, |
89 bool& incremental_install) { | 87 bool& incremental_install) { |
90 // First uncompress the payload. This could be a differential | 88 // First uncompress the payload. This could be a differential |
91 // update (patch.7z) or full archive (chrome.7z). If this uncompress fails | 89 // update (patch.7z) or full archive (chrome.7z). If this uncompress fails |
92 // return with error. | 90 // return with error. |
93 std::wstring unpacked_file; | 91 std::wstring unpacked_file; |
94 int32 ret = LzmaUtil::UnPackArchive(archive.value(), temp_path.value(), | 92 int32 ret = LzmaUtil::UnPackArchive(archive.value(), temp_path.value(), |
95 &unpacked_file); | 93 &unpacked_file); |
96 if (ret != NO_ERROR) | 94 if (ret != NO_ERROR) |
97 return ret; | 95 return ret; |
98 | 96 |
99 FilePath uncompressed_archive(temp_path.Append(installer::kChromeArchive)); | 97 FilePath uncompressed_archive(temp_path.Append(installer::kChromeArchive)); |
100 scoped_ptr<Version> archive_version( | 98 scoped_ptr<Version> archive_version( |
101 installer::GetVersionFromArchiveDir(installation.path())); | 99 installer::GetVersionFromArchiveDir(installer_state.target_path())); |
102 | 100 |
103 // Check if this is differential update and if it is, patch it to the | 101 // Check if this is differential update and if it is, patch it to the |
104 // installer archive that should already be on the machine. We assume | 102 // installer archive that should already be on the machine. We assume |
105 // it is a differential installer if chrome.7z is not found. | 103 // it is a differential installer if chrome.7z is not found. |
106 if (!file_util::PathExists(uncompressed_archive)) { | 104 if (!file_util::PathExists(uncompressed_archive)) { |
107 incremental_install = true; | 105 incremental_install = true; |
108 VLOG(1) << "Differential patch found. Applying to existing archive."; | 106 VLOG(1) << "Differential patch found. Applying to existing archive."; |
109 if (!archive_version.get()) { | 107 if (!archive_version.get()) { |
110 LOG(ERROR) << "Can not use differential update when Chrome is not " | 108 LOG(ERROR) << "Can not use differential update when Chrome is not " |
111 << "installed on the system."; | 109 << "installed on the system."; |
112 return installer::CHROME_NOT_INSTALLED; | 110 return installer::CHROME_NOT_INSTALLED; |
113 } | 111 } |
114 | 112 |
115 FilePath existing_archive(installation.path().Append( | 113 FilePath existing_archive(installer_state.target_path().Append( |
116 UTF8ToWide(archive_version->GetString()))); | 114 UTF8ToWide(archive_version->GetString()))); |
117 existing_archive = existing_archive.Append(installer::kInstallerDir); | 115 existing_archive = existing_archive.Append(installer::kInstallerDir); |
118 existing_archive = existing_archive.Append(installer::kChromeArchive); | 116 existing_archive = existing_archive.Append(installer::kChromeArchive); |
119 if (int i = installer::ApplyDiffPatch(FilePath(existing_archive), | 117 if (int i = installer::ApplyDiffPatch(FilePath(existing_archive), |
120 FilePath(unpacked_file), | 118 FilePath(unpacked_file), |
121 FilePath(uncompressed_archive))) { | 119 FilePath(uncompressed_archive))) { |
122 LOG(ERROR) << "Binary patching failed with error " << i; | 120 LOG(ERROR) << "Binary patching failed with error " << i; |
123 return i; | 121 return i; |
124 } | 122 } |
125 } | 123 } |
126 | 124 |
127 // Unpack the uncompressed archive. | 125 // Unpack the uncompressed archive. |
128 return LzmaUtil::UnPackArchive(uncompressed_archive.value(), | 126 return LzmaUtil::UnPackArchive(uncompressed_archive.value(), |
129 output_directory.value(), &unpacked_file); | 127 output_directory.value(), &unpacked_file); |
130 } | 128 } |
131 | 129 |
132 | 130 |
133 // This function is called when --rename-chrome-exe option is specified on | 131 // This function is called when --rename-chrome-exe option is specified on |
134 // setup.exe command line. This function assumes an in-use update has happened | 132 // setup.exe command line. This function assumes an in-use update has happened |
135 // for Chrome so there should be a file called new_chrome.exe on the file | 133 // for Chrome so there should be a file called new_chrome.exe on the file |
136 // system and a key called 'opv' in the registry. This function will move | 134 // system and a key called 'opv' in the registry. This function will move |
137 // new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. | 135 // new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. |
138 installer::InstallStatus RenameChromeExecutables( | 136 installer::InstallStatus RenameChromeExecutables( |
139 const Package& installation) { | 137 const InstallerState& installer_state) { |
140 FilePath chrome_exe(installation.path().Append(installer::kChromeExe)); | 138 const FilePath &target_path = installer_state.target_path(); |
141 FilePath chrome_old_exe(installation.path().Append( | 139 FilePath chrome_exe(target_path.Append(installer::kChromeExe)); |
142 installer::kChromeOldExe)); | 140 FilePath chrome_old_exe(target_path.Append(installer::kChromeOldExe)); |
143 FilePath chrome_new_exe(installation.path().Append( | 141 FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe)); |
144 installer::kChromeNewExe)); | |
145 | 142 |
146 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); | 143 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
147 install_list->AddDeleteTreeWorkItem(chrome_old_exe); | 144 install_list->AddDeleteTreeWorkItem(chrome_old_exe); |
148 FilePath temp_path; | 145 FilePath temp_path; |
149 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { | 146 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { |
150 LOG(ERROR) << "Failed to create Temp directory " << temp_path.value(); | 147 LOG(ERROR) << "Failed to create Temp directory " << temp_path.value(); |
151 return installer::RENAME_FAILED; | 148 return installer::RENAME_FAILED; |
152 } | 149 } |
153 | 150 |
154 install_list->AddCopyTreeWorkItem(chrome_new_exe.value(), | 151 install_list->AddCopyTreeWorkItem(chrome_new_exe.value(), |
155 chrome_exe.value(), | 152 chrome_exe.value(), |
156 temp_path.ToWStringHack(), | 153 temp_path.ToWStringHack(), |
157 WorkItem::IF_DIFFERENT, | 154 WorkItem::IF_DIFFERENT, |
158 std::wstring()); | 155 std::wstring()); |
159 install_list->AddDeleteTreeWorkItem(chrome_new_exe); | 156 install_list->AddDeleteTreeWorkItem(chrome_new_exe); |
160 | 157 |
161 HKEY reg_root = installation.system_level() ? HKEY_LOCAL_MACHINE : | 158 HKEY reg_root = installer_state.root_key(); |
162 HKEY_CURRENT_USER; | 159 const Products& products = installer_state.products(); |
163 const Products& products = installation.products(); | |
164 for (size_t i = 0; i < products.size(); ++i) { | 160 for (size_t i = 0; i < products.size(); ++i) { |
165 const Product* product = products[i]; | 161 const Product* product = products[i]; |
166 BrowserDistribution* browser_dist = product->distribution(); | 162 BrowserDistribution* browser_dist = product->distribution(); |
167 std::wstring version_key(browser_dist->GetVersionKey()); | 163 std::wstring version_key(browser_dist->GetVersionKey()); |
168 install_list->AddDeleteRegValueWorkItem(reg_root, | 164 install_list->AddDeleteRegValueWorkItem(reg_root, |
169 version_key, | 165 version_key, |
170 google_update::kRegOldVersionField); | 166 google_update::kRegOldVersionField); |
171 install_list->AddDeleteRegValueWorkItem(reg_root, | 167 install_list->AddDeleteRegValueWorkItem(reg_root, |
172 version_key, | 168 version_key, |
173 google_update::kRegRenameCmdField); | 169 google_update::kRegRenameCmdField); |
174 } | 170 } |
175 installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; | 171 installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; |
176 if (!install_list->Do()) { | 172 if (!install_list->Do()) { |
177 LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; | 173 LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; |
178 install_list->Rollback(); | 174 install_list->Rollback(); |
179 ret = installer::RENAME_FAILED; | 175 ret = installer::RENAME_FAILED; |
180 } | 176 } |
181 file_util::Delete(temp_path, true); | 177 file_util::Delete(temp_path, true); |
182 return ret; | 178 return ret; |
183 } | 179 } |
184 | 180 |
181 // The supported multi-install | |
grt (UTC plus 2)
2011/01/25 03:21:52
self: fix this crazy line wrap
| |
182 // modes are: | |
183 // --multi-install --chrome --chrome-frame --ready-mode | |
184 // - If a non-multi Chrome Frame installation is present, Chrome Frame is | |
185 // removed from |installer_state|'s list of products (thereby preserving | |
186 // the existing SxS install). | |
187 // - If a multi Chrome Frame installation is present, its options are | |
188 // preserved (i.e., the --ready-mode command-line option is ignored). | |
189 // --multi-install --chrome-frame | |
190 // - If a non-multi Chrome Frame installation is present, fail. | |
191 // - If a Chrome installation on a different channel is present, fail. | |
192 // - If --ready-mode and no Chrome installation is present, fail. | |
193 // - If a Chrome installation is present, add it to the set of products to | |
194 // install. | |
195 bool CheckMultiInstallConditions(const InstallationState& original_state, | |
196 InstallerState* installer_state, | |
197 installer::InstallStatus* status) { | |
198 const Products& products = installer_state->products(); | |
199 DCHECK(products.size()); | |
200 | |
201 bool is_first_install = true; | |
202 const bool system_level = installer_state->system_install(); | |
203 | |
204 if (installer_state->is_multi_install()) { | |
205 const Product* chrome = | |
206 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | |
207 const Product* chrome_frame = | |
208 installer_state->FindProduct(BrowserDistribution::CHROME_FRAME); | |
209 const ProductState* cf_state = | |
210 original_state.GetProductState(system_level, | |
211 BrowserDistribution::CHROME_FRAME); | |
212 if (chrome != NULL) { | |
213 if (chrome_frame != NULL && | |
214 chrome_frame->HasOption(installer::kOptionReadyMode)) { | |
215 // We're being asked to install Chrome with Chrome Frame in ready-mode. | |
216 // This is an optimistic operation: if a SxS install of Chrome Frame | |
217 // is already present, don't touch it; if a multi-install of Chrome | |
218 // Frame is present, preserve its settings (ready-mode, CEEE). | |
219 if (cf_state != NULL) { | |
220 installer_state->RemoveProduct(chrome_frame); | |
221 chrome_frame = NULL; | |
222 if (cf_state->is_multi_install()) { | |
223 chrome_frame = installer_state->AddProductFromState( | |
224 BrowserDistribution::CHROME_FRAME, *cf_state); | |
225 VLOG(1) << "Upgrading existing multi-install Chrome Frame rather " | |
226 "than installing in ready-mode."; | |
227 } else { | |
228 VLOG(1) << "Skipping upgrade of single-install Chrome Frame rather " | |
229 "than installing in ready-mode."; | |
230 } | |
231 } else { | |
232 VLOG(1) << "Performing initial install of Chrome Frame ready-mode."; | |
233 } | |
234 } | |
235 } else if (chrome_frame != NULL) { | |
236 // We're being asked to install or update Chrome Frame alone. | |
237 const ProductState* chrome_state = | |
238 original_state.GetProductState(system_level, | |
239 BrowserDistribution::CHROME_BROWSER); | |
240 if (chrome_state != NULL) { | |
241 base::win::RegKey key; | |
242 installer::ChannelInfo cf_channel; | |
243 // Chrome Frame may not yet be installed, so peek into the registry | |
244 // directly to see what channel Google Update has specified. There will | |
245 // be no value if we're not being managed by Google Update. | |
246 if (key.Open(installer_state->root_key(), | |
247 chrome_frame->distribution()->GetStateKey().c_str(), | |
248 KEY_QUERY_VALUE) == ERROR_SUCCESS) { | |
249 cf_channel.Initialize(key); | |
250 } | |
251 // Fail if Chrome is already installed but is on a different update | |
252 // channel. | |
253 if (!cf_channel.EqualsBaseOf(chrome_state->channel())) { | |
254 *status = installer::CONFLICTING_CHANNEL_EXISTS; | |
255 InstallUtil::WriteInstallerResult(system_level, | |
256 installer_state->state_key(), *status, | |
257 IDS_INSTALL_CONFLICTING_CHANNEL_EXISTS_BASE, NULL); | |
258 return false; | |
259 } | |
260 // Otherwise, add Chrome to the set of products (making it multi-install | |
261 // in the process) so that it is updated, too. | |
262 scoped_ptr<Product> multi_chrome(new Product( | |
263 BrowserDistribution::GetSpecificDistribution( | |
264 BrowserDistribution::CHROME_BROWSER))); | |
265 multi_chrome->SetOption(installer::kOptionMultiInstall, true); | |
266 chrome = installer_state->AddProduct(&multi_chrome); | |
267 VLOG(1) << "Upgrading existing multi-install Chrome browser along with " | |
268 << chrome_frame->distribution()->GetApplicationName(); | |
269 } else if (chrome_frame->HasOption(installer::kOptionReadyMode)) { | |
270 // Chrome Frame with ready-mode is to be installed, yet Chrome is | |
271 // neither installed nor being installed. Fail. | |
272 *status = installer::READY_MODE_REQUIRES_CHROME; | |
273 InstallUtil::WriteInstallerResult(system_level, | |
274 installer_state->state_key(), *status, | |
275 IDS_INSTALL_READY_MODE_REQUIRES_CHROME_BASE, NULL); | |
276 return false; | |
277 } | |
278 } | |
279 | |
280 // Fail if we're installing Chrome Frame yet a single-install of it is | |
tommi (sloooow) - chröme
2011/01/24 20:25:44
yet -> if
robertshield
2011/01/25 03:03:42
if -> when
grt (UTC plus 2)
2011/01/25 03:09:40
"yet" is what is meant there. If you don't like "
grt (UTC plus 2)
2011/01/25 03:21:52
yet -> but -> if -> when -> ?
(okay, "when" is nic
tommi (sloooow) - chröme
2011/01/25 14:00:55
I see. I read it as being a comment for the 'if'
| |
281 // already installed. | |
282 // TODO(grt): Add support for migration of Chrome Frame from single- to | |
283 // multi-install. | |
284 if (chrome_frame != NULL && | |
285 cf_state != NULL && !cf_state->is_multi_install()) { | |
286 *status = installer::NON_MULTI_INSTALLATION_EXISTS; | |
287 InstallUtil::WriteInstallerResult(system_level, | |
288 installer_state->state_key(), *status, | |
289 IDS_INSTALL_NON_MULTI_INSTALLATION_EXISTS_BASE, NULL); | |
290 return false; | |
291 } | |
292 } else if (DCHECK_IS_ON()) { | |
293 // It isn't possible to stuff two products into a single-install | |
294 // InstallerState. Abort the process here in debug builds just in case | |
295 // someone finds a way. | |
296 DCHECK_EQ(1U, products.size()); | |
297 } | |
298 | |
299 return true; | |
300 } | |
301 | |
302 // In multi-install, adds all products to |installer_state| that are | |
303 // multi-installed and must be updated along with the products already present | |
304 // in |installer_state|. | |
305 void AddExistingMultiInstalls(const InstallationState& original_state, | |
306 InstallerState* installer_state) { | |
307 if (installer_state->is_multi_install()) { | |
308 BrowserDistribution::Type product_checks[] = { | |
309 BrowserDistribution::CHROME_BROWSER, | |
310 BrowserDistribution::CHROME_FRAME | |
311 }; | |
312 | |
313 for (size_t i = 0; i < arraysize(product_checks); ++i) { | |
314 BrowserDistribution::Type type = product_checks[i]; | |
315 if (!installer_state->FindProduct(type)) { | |
316 const ProductState* state = | |
317 original_state.GetProductState(installer_state->system_install(), | |
318 type); | |
319 if ((state != NULL) && state->is_multi_install()) { | |
320 installer_state->AddProductFromState(type, *state); | |
321 VLOG(1) << "Product already installed and must be included: " | |
322 << BrowserDistribution::GetSpecificDistribution( | |
323 type)->GetApplicationName(); | |
324 } | |
325 } | |
326 } | |
327 } | |
328 } | |
329 | |
330 // Checks for compatibility between the current state of the system and the | |
robertshield
2011/01/25 03:03:42
indent
grt (UTC plus 2)
2011/01/25 03:21:52
Done.
| |
331 // desired operation. Also applies policy that mutates the desired operation; | |
332 // specifically, the |installer_state| object. | |
333 // Also blocks simultaneous user-level and system-level installs. In the case | |
334 // of trying to install user-level Chrome when system-level exists, the | |
335 // existing system-level Chrome is launched. | |
185 bool CheckPreInstallConditions(const InstallationState& original_state, | 336 bool CheckPreInstallConditions(const InstallationState& original_state, |
186 const InstallerState& installer_state, | 337 InstallerState* installer_state, |
187 const Package& installation, | |
188 const MasterPreferences& prefs, | |
189 installer::InstallStatus* status) { | 338 installer::InstallStatus* status) { |
190 const Products& products = installation.products(); | 339 const Products& products = installer_state->products(); |
191 DCHECK(products.size()); | 340 DCHECK(products.size()); |
192 | 341 |
342 if (!CheckMultiInstallConditions(original_state, installer_state, status)) | |
343 return false; | |
344 | |
193 bool is_first_install = true; | 345 bool is_first_install = true; |
194 const bool system_level = installation.system_level(); | 346 const bool system_level = installer_state->system_install(); |
195 | 347 |
196 for (size_t i = 0; i < products.size(); ++i) { | 348 for (size_t i = 0; i < products.size(); ++i) { |
197 const Product* product = products[i]; | 349 const Product* product = products[i]; |
198 BrowserDistribution* browser_dist = product->distribution(); | 350 BrowserDistribution* browser_dist = product->distribution(); |
351 | |
352 // Check for an existing installation of the product. | |
199 const ProductState* product_state = | 353 const ProductState* product_state = |
200 original_state.GetProductState(system_level, browser_dist->GetType()); | 354 original_state.GetProductState(system_level, browser_dist->GetType()); |
201 if (product_state != NULL) | 355 if (product_state != NULL) { |
202 is_first_install = false; | 356 is_first_install = false; |
357 // Block downgrades from multi-install to single-install. | |
358 if (!installer_state->is_multi_install() && | |
359 product_state->is_multi_install()) { | |
360 *status = installer::MULTI_INSTALLATION_EXISTS; | |
361 InstallUtil::WriteInstallerResult(system_level, | |
362 installer_state->state_key(), *status, | |
363 IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE, NULL); | |
364 return false; | |
365 } | |
366 } | |
203 | 367 |
204 // Check to avoid simultaneous per-user and per-machine installs. | 368 // Check to avoid simultaneous per-user and per-machine installs. |
205 const ProductState* other_state = | 369 const ProductState* other_state = |
206 original_state.GetProductState(!system_level, browser_dist->GetType()); | 370 original_state.GetProductState(!system_level, browser_dist->GetType()); |
207 | |
208 if (other_state != NULL) { | 371 if (other_state != NULL) { |
209 LOG(ERROR) << "Already installed version " | 372 LOG(ERROR) << "Already installed version " |
210 << other_state->version().GetString() | 373 << other_state->version().GetString() |
211 << " conflicts with the current install mode."; | 374 << " conflicts with the current install mode."; |
212 if (!system_level && is_first_install && product->is_chrome()) { | 375 if (!system_level && is_first_install && product->is_chrome()) { |
213 // This is user-level install and there is a system-level chrome | 376 // This is user-level install and there is a system-level chrome |
214 // installation. Instruct Omaha to launch the existing one. There | 377 // installation. Instruct Google Update to launch the existing one. |
215 // should be no error dialog. | 378 // There should be no error dialog. |
216 FilePath chrome_exe(installer::GetChromeInstallPath(!system_level, | 379 FilePath chrome_exe(installer::GetChromeInstallPath(!system_level, |
217 browser_dist)); | 380 browser_dist)); |
218 if (chrome_exe.empty()) { | 381 if (chrome_exe.empty()) { |
219 // If we failed to construct install path. Give up. | 382 // If we failed to construct install path. Give up. |
220 *status = installer::OS_ERROR; | 383 *status = installer::OS_ERROR; |
221 InstallUtil::WriteInstallerResult(system_level, | 384 InstallUtil::WriteInstallerResult(system_level, |
222 installer_state.state_key(), *status, IDS_INSTALL_OS_ERROR_BASE, | 385 installer_state->state_key(), *status, IDS_INSTALL_OS_ERROR_BASE, |
223 NULL); | 386 NULL); |
224 } else { | 387 } else { |
225 *status = installer::EXISTING_VERSION_LAUNCHED; | 388 *status = installer::EXISTING_VERSION_LAUNCHED; |
226 chrome_exe = chrome_exe.Append(installer::kChromeExe); | 389 chrome_exe = chrome_exe.Append(installer::kChromeExe); |
227 CommandLine cmd(chrome_exe); | 390 CommandLine cmd(chrome_exe); |
228 cmd.AppendSwitch(switches::kFirstRun); | 391 cmd.AppendSwitch(switches::kFirstRun); |
229 InstallUtil::WriteInstallerResult(system_level, | 392 InstallUtil::WriteInstallerResult(system_level, |
230 installer_state.state_key(), *status, 0, NULL); | 393 installer_state->state_key(), *status, 0, NULL); |
231 VLOG(1) << "Launching existing system-level chrome instead."; | 394 VLOG(1) << "Launching existing system-level chrome instead."; |
232 base::LaunchApp(cmd, false, false, NULL); | 395 base::LaunchApp(cmd, false, false, NULL); |
233 } | 396 } |
234 return false; | 397 return false; |
235 } | 398 } |
236 | 399 |
237 // If the following compile assert fires it means that the InstallStatus | 400 // If the following compile assert fires it means that the InstallStatus |
238 // enumeration changed which will break the contract between the old | 401 // enumeration changed which will break the contract between the old |
239 // chrome installed and the new setup.exe that is trying to upgrade. | 402 // chrome installed and the new setup.exe that is trying to upgrade. |
240 COMPILE_ASSERT(installer::SXS_OPTION_NOT_SUPPORTED == 33, | 403 COMPILE_ASSERT(installer::CONFLICTING_CHANNEL_EXISTS == 39, |
241 dont_change_enum); | 404 dont_change_enum); |
242 | 405 |
243 // This is an update, not an install. Omaha should know the difference | 406 // This is an update, not an install. Omaha should know the difference |
244 // and not show a dialog. | 407 // and not show a dialog. |
245 *status = system_level ? installer::USER_LEVEL_INSTALL_EXISTS : | 408 *status = system_level ? installer::USER_LEVEL_INSTALL_EXISTS : |
246 installer::SYSTEM_LEVEL_INSTALL_EXISTS; | 409 installer::SYSTEM_LEVEL_INSTALL_EXISTS; |
247 int str_id = system_level ? IDS_INSTALL_USER_LEVEL_EXISTS_BASE : | 410 int str_id = system_level ? IDS_INSTALL_USER_LEVEL_EXISTS_BASE : |
248 IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE; | 411 IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE; |
249 InstallUtil::WriteInstallerResult(system_level, | 412 InstallUtil::WriteInstallerResult(system_level, |
250 installer_state.state_key(), *status, str_id, NULL); | 413 installer_state->state_key(), *status, str_id, NULL); |
251 return false; | 414 return false; |
252 } | 415 } |
253 } | 416 } |
254 | 417 |
418 // See what products are already installed in multi mode. When we do multi | |
419 // installs, we must upgrade all installations since they share the binaries. | |
420 AddExistingMultiInstalls(original_state, installer_state); | |
421 | |
255 // If no previous installation of Chrome, make sure installation directory | 422 // If no previous installation of Chrome, make sure installation directory |
256 // either does not exist or can be deleted (i.e. is not locked by some other | 423 // either does not exist or can be deleted (i.e. is not locked by some other |
257 // process). | 424 // process). |
258 if (is_first_install) { | 425 if (is_first_install) { |
259 if (file_util::PathExists(installation.path()) && | 426 if (file_util::PathExists(installer_state->target_path()) && |
260 !file_util::Delete(installation.path(), true)) { | 427 !file_util::Delete(installer_state->target_path(), true)) { |
261 LOG(ERROR) << "Installation directory " << installation.path().value() | 428 LOG(ERROR) << "Installation directory " |
429 << installer_state->target_path().value() | |
262 << " exists and can not be deleted."; | 430 << " exists and can not be deleted."; |
263 *status = installer::INSTALL_DIR_IN_USE; | 431 *status = installer::INSTALL_DIR_IN_USE; |
264 int str_id = IDS_INSTALL_DIR_IN_USE_BASE; | 432 int str_id = IDS_INSTALL_DIR_IN_USE_BASE; |
265 InstallUtil::WriteInstallerResult(system_level, | 433 InstallUtil::WriteInstallerResult(system_level, |
266 installer_state.state_key(), *status, str_id, NULL); | 434 installer_state->state_key(), *status, str_id, NULL); |
267 return false; | 435 return false; |
268 } | 436 } |
269 } | 437 } |
270 | 438 |
271 return true; | 439 return true; |
272 } | 440 } |
273 | 441 |
274 installer::InstallStatus InstallChrome(const InstallationState& original_state, | 442 installer::InstallStatus InstallProducts( |
275 const InstallerState& installer_state, | 443 const InstallationState& original_state, |
276 const CommandLine& cmd_line, const Package& installation, | 444 const CommandLine& cmd_line, |
277 const MasterPreferences& prefs) { | 445 const MasterPreferences& prefs, |
446 InstallerState* installer_state) { | |
447 const bool system_install = installer_state->system_install(); | |
278 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | 448 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; |
279 if (!CheckPreInstallConditions(original_state, installer_state, installation, | 449 if (!CheckPreInstallConditions(original_state, installer_state, |
280 prefs, &install_status)) | 450 &install_status)) |
281 return install_status; | 451 return install_status; |
282 | 452 |
283 // For install the default location for chrome.packed.7z is in current | 453 // For install the default location for chrome.packed.7z is in current |
284 // folder, so get that value first. | 454 // folder, so get that value first. |
285 FilePath archive(cmd_line.GetProgram().DirName().Append( | 455 FilePath archive(cmd_line.GetProgram().DirName().Append( |
286 installer::kChromeCompressedArchive)); | 456 installer::kChromeCompressedArchive)); |
287 | 457 |
288 // If --install-archive is given, get the user specified value | 458 // If --install-archive is given, get the user specified value |
289 if (cmd_line.HasSwitch(installer::switches::kInstallArchive)) { | 459 if (cmd_line.HasSwitch(installer::switches::kInstallArchive)) { |
290 archive = cmd_line.GetSwitchValuePath( | 460 archive = cmd_line.GetSwitchValuePath( |
291 installer::switches::kInstallArchive); | 461 installer::switches::kInstallArchive); |
292 } | 462 } |
293 VLOG(1) << "Archive found to install Chrome " << archive.value(); | 463 VLOG(1) << "Archive found to install Chrome " << archive.value(); |
294 const Products& products = installation.products(); | 464 const Products& products = installer_state->products(); |
295 | 465 |
296 // Create a temp folder where we will unpack Chrome archive. If it fails, | 466 // Create a temp folder where we will unpack Chrome archive. If it fails, |
297 // then we are doomed, so return immediately and no cleanup is required. | 467 // then we are doomed, so return immediately and no cleanup is required. |
298 FilePath temp_path; | 468 FilePath temp_path; |
299 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { | 469 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { |
300 LOG(ERROR) << "Could not create temporary path."; | 470 LOG(ERROR) << "Could not create temporary path."; |
301 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 471 InstallUtil::WriteInstallerResult(system_install, |
302 installer_state.state_key(), installer::TEMP_DIR_FAILED, | 472 installer_state->state_key(), installer::TEMP_DIR_FAILED, |
303 IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL); | 473 IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL); |
304 return installer::TEMP_DIR_FAILED; | 474 return installer::TEMP_DIR_FAILED; |
305 } | 475 } |
306 VLOG(1) << "created path " << temp_path.value(); | 476 VLOG(1) << "created path " << temp_path.value(); |
307 | 477 |
308 FilePath unpack_path(temp_path.Append(installer::kInstallSourceDir)); | 478 FilePath unpack_path(temp_path.Append(installer::kInstallSourceDir)); |
309 bool incremental_install = false; | 479 bool incremental_install = false; |
310 if (UnPackArchive(archive, installation, temp_path, unpack_path, | 480 if (UnPackArchive(archive, *installer_state, temp_path, unpack_path, |
311 incremental_install)) { | 481 incremental_install)) { |
312 install_status = installer::UNCOMPRESSION_FAILED; | 482 install_status = installer::UNCOMPRESSION_FAILED; |
313 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 483 InstallUtil::WriteInstallerResult(system_install, |
314 installer_state.state_key(), install_status, | 484 installer_state->state_key(), install_status, |
315 IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, NULL); | 485 IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, NULL); |
316 } else { | 486 } else { |
317 VLOG(1) << "unpacked to " << unpack_path.value(); | 487 VLOG(1) << "unpacked to " << unpack_path.value(); |
318 FilePath src_path(unpack_path.Append(installer::kInstallSourceChromeDir)); | 488 FilePath src_path(unpack_path.Append(installer::kInstallSourceChromeDir)); |
319 scoped_ptr<Version> | 489 scoped_ptr<Version> |
320 installer_version(installer::GetVersionFromArchiveDir(src_path)); | 490 installer_version(installer::GetVersionFromArchiveDir(src_path)); |
321 if (!installer_version.get()) { | 491 if (!installer_version.get()) { |
322 LOG(ERROR) << "Did not find any valid version in installer."; | 492 LOG(ERROR) << "Did not find any valid version in installer."; |
323 install_status = installer::INVALID_ARCHIVE; | 493 install_status = installer::INVALID_ARCHIVE; |
324 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 494 InstallUtil::WriteInstallerResult(system_install, |
325 installer_state.state_key(), install_status, | 495 installer_state->state_key(), install_status, |
326 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); | 496 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); |
327 } else { | 497 } else { |
328 // TODO(tommi): Move towards having only a single version that is common | 498 // TODO(tommi): Move towards having only a single version that is common |
329 // to all products. Only the package should have a version since it | 499 // to all products. Only the package should have a version since it |
330 // represents all the binaries. When a single product is upgraded, all | 500 // represents all the binaries. When a single product is upgraded, all |
331 // currently installed product for the shared binary installation, should | 501 // currently installed product for the shared binary installation, should |
332 // (or rather must) be upgraded. | 502 // (or rather must) be upgraded. |
333 VLOG(1) << "version to install: " << installer_version->GetString(); | 503 VLOG(1) << "version to install: " << installer_version->GetString(); |
334 bool higher_version_installed = false; | 504 bool higher_version_installed = false; |
335 for (size_t i = 0; i < installation.products().size(); ++i) { | 505 for (size_t i = 0; i < installer_state->products().size(); ++i) { |
336 const Product* product = installation.products()[i]; | 506 const Product* product = installer_state->products()[i]; |
337 const ProductState* product_state = | 507 const ProductState* product_state = |
338 original_state.GetProductState(installer_state.system_install(), | 508 original_state.GetProductState(system_install, |
339 product->distribution()->GetType()); | 509 product->distribution()->GetType()); |
340 if (product_state != NULL && | 510 if (product_state != NULL && |
341 (product_state->version().CompareTo(*installer_version) > 0)) { | 511 (product_state->version().CompareTo(*installer_version) > 0)) { |
342 LOG(ERROR) << "Higher version is already installed."; | 512 LOG(ERROR) << "Higher version is already installed."; |
343 higher_version_installed = true; | 513 higher_version_installed = true; |
344 install_status = installer::HIGHER_VERSION_EXISTS; | 514 install_status = installer::HIGHER_VERSION_EXISTS; |
345 | 515 |
346 if (product->is_chrome()) { | 516 if (product->is_chrome()) { |
347 // TODO(robertshield): We should take the installer result text | 517 // TODO(robertshield): We should take the installer result text |
348 // strings from the Product. | 518 // strings from the Product. |
349 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 519 InstallUtil::WriteInstallerResult(system_install, |
350 installer_state.state_key(), install_status, | 520 installer_state->state_key(), install_status, |
351 IDS_INSTALL_HIGHER_VERSION_BASE, NULL); | 521 IDS_INSTALL_HIGHER_VERSION_BASE, NULL); |
352 } else { | 522 } else { |
353 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 523 InstallUtil::WriteInstallerResult(system_install, |
354 installer_state.state_key(), install_status, | 524 installer_state->state_key(), install_status, |
355 IDS_INSTALL_HIGHER_VERSION_CF_BASE, NULL); | 525 IDS_INSTALL_HIGHER_VERSION_CF_BASE, NULL); |
356 } | 526 } |
357 } | 527 } |
358 } | 528 } |
359 | 529 |
360 if (!higher_version_installed) { | 530 if (!higher_version_installed) { |
361 // We want to keep uncompressed archive (chrome.7z) that we get after | 531 // We want to keep uncompressed archive (chrome.7z) that we get after |
362 // uncompressing and binary patching. Get the location for this file. | 532 // uncompressing and binary patching. Get the location for this file. |
363 FilePath archive_to_copy(temp_path.Append(installer::kChromeArchive)); | 533 FilePath archive_to_copy(temp_path.Append(installer::kChromeArchive)); |
364 FilePath prefs_source_path(cmd_line.GetSwitchValueNative( | 534 FilePath prefs_source_path(cmd_line.GetSwitchValueNative( |
365 installer::switches::kInstallerData)); | 535 installer::switches::kInstallerData)); |
366 install_status = installer::InstallOrUpdateProduct(original_state, | 536 install_status = installer::InstallOrUpdateProduct(original_state, |
367 installer_state, cmd_line.GetProgram(), archive_to_copy, temp_path, | 537 *installer_state, cmd_line.GetProgram(), archive_to_copy, temp_path, |
368 prefs_source_path, prefs, *installer_version, installation); | 538 prefs_source_path, prefs, *installer_version); |
369 | 539 |
370 int install_msg_base = IDS_INSTALL_FAILED_BASE; | 540 int install_msg_base = IDS_INSTALL_FAILED_BASE; |
371 std::wstring chrome_exe; | 541 std::wstring chrome_exe; |
372 if (install_status == installer::SAME_VERSION_REPAIR_FAILED) { | 542 if (install_status == installer::SAME_VERSION_REPAIR_FAILED) { |
373 if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) { | 543 if (installer_state->FindProduct(BrowserDistribution::CHROME_FRAME)) { |
374 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE; | 544 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE; |
375 } else { | 545 } else { |
376 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE; | 546 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE; |
377 } | 547 } |
378 } else if (install_status != installer::INSTALL_FAILED) { | 548 } else if (install_status != installer::INSTALL_FAILED) { |
379 if (installation.path().empty()) { | 549 if (installer_state->target_path().empty()) { |
380 // If we failed to construct install path, it means the OS call to | 550 // If we failed to construct install path, it means the OS call to |
381 // get %ProgramFiles% or %AppData% failed. Report this as failure. | 551 // get %ProgramFiles% or %AppData% failed. Report this as failure. |
382 install_msg_base = IDS_INSTALL_OS_ERROR_BASE; | 552 install_msg_base = IDS_INSTALL_OS_ERROR_BASE; |
383 install_status = installer::OS_ERROR; | 553 install_status = installer::OS_ERROR; |
384 } else { | 554 } else { |
385 chrome_exe = installation.path() | 555 chrome_exe = installer_state->target_path() |
386 .Append(installer::kChromeExe).value(); | 556 .Append(installer::kChromeExe).value(); |
387 chrome_exe = L"\"" + chrome_exe + L"\""; | 557 chrome_exe = L"\"" + chrome_exe + L"\""; |
388 install_msg_base = 0; | 558 install_msg_base = 0; |
389 } | 559 } |
390 } | 560 } |
391 | 561 |
392 const Product* chrome_install = | 562 // Only do Chrome-specific stuff (like launching the browser) if |
393 FindProduct(products, BrowserDistribution::CHROME_BROWSER); | 563 // Chrome was specifically requested (rather than being upgraded as |
564 // part of a multi-install. | |
robertshield
2011/01/25 03:03:42
close parenthesis
grt (UTC plus 2)
2011/01/25 03:21:52
Done.
| |
565 const Product* chrome_install = prefs.install_chrome() ? | |
566 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER) : | |
567 NULL; | |
394 | 568 |
395 bool value = false; | 569 bool value = false; |
396 if (chrome_install) { | 570 if (chrome_install) { |
397 prefs.GetBool( | 571 prefs.GetBool( |
398 installer::master_preferences::kDoNotRegisterForUpdateLaunch, | 572 installer::master_preferences::kDoNotRegisterForUpdateLaunch, |
399 &value); | 573 &value); |
400 } else { | 574 } else { |
401 value = true; // Never register. | 575 value = true; // Never register. |
402 } | 576 } |
403 | 577 |
404 bool write_chrome_launch_string = (!value) && | 578 bool write_chrome_launch_string = (!value) && |
405 (install_status != installer::IN_USE_UPDATED); | 579 (install_status != installer::IN_USE_UPDATED); |
406 | 580 |
407 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 581 InstallUtil::WriteInstallerResult(system_install, |
408 installer_state.state_key(), install_status, install_msg_base, | 582 installer_state->state_key(), install_status, install_msg_base, |
409 write_chrome_launch_string ? &chrome_exe : NULL); | 583 write_chrome_launch_string ? &chrome_exe : NULL); |
410 | 584 |
411 if (install_status == installer::FIRST_INSTALL_SUCCESS) { | 585 if (install_status == installer::FIRST_INSTALL_SUCCESS) { |
412 VLOG(1) << "First install successful."; | 586 VLOG(1) << "First install successful."; |
413 if (chrome_install) { | 587 if (chrome_install) { |
414 // We never want to launch Chrome in system level install mode. | 588 // We never want to launch Chrome in system level install mode. |
415 bool do_not_launch_chrome = false; | 589 bool do_not_launch_chrome = false; |
416 prefs.GetBool( | 590 prefs.GetBool( |
417 installer::master_preferences::kDoNotLaunchChrome, | 591 installer::master_preferences::kDoNotLaunchChrome, |
418 &do_not_launch_chrome); | 592 &do_not_launch_chrome); |
419 if (!installation.system_level() && !do_not_launch_chrome) | 593 if (!system_install && !do_not_launch_chrome) |
420 chrome_install->LaunchChrome(); | 594 chrome_install->LaunchChrome(installer_state->target_path()); |
421 } | 595 } |
422 } else if ((install_status == installer::NEW_VERSION_UPDATED) || | 596 } else if ((install_status == installer::NEW_VERSION_UPDATED) || |
423 (install_status == installer::IN_USE_UPDATED)) { | 597 (install_status == installer::IN_USE_UPDATED)) { |
424 for (size_t i = 0; i < products.size(); ++i) { | 598 for (size_t i = 0; i < products.size(); ++i) { |
425 installer::RemoveLegacyRegistryKeys( | 599 installer::RemoveLegacyRegistryKeys( |
426 products[i]->distribution()); | 600 products[i]->distribution()); |
427 } | 601 } |
428 } | 602 } |
429 } | 603 } |
430 } | 604 } |
431 // There might be an experiment (for upgrade usually) that needs to happen. | 605 // There might be an experiment (for upgrade usually) that needs to happen. |
432 // An experiment's outcome can include chrome's uninstallation. If that is | 606 // An experiment's outcome can include chrome's uninstallation. If that is |
433 // the case we would not do that directly at this point but in another | 607 // the case we would not do that directly at this point but in another |
434 // instance of setup.exe | 608 // instance of setup.exe |
435 // | 609 // |
436 // There is another way to reach this same function if this is a system | 610 // There is another way to reach this same function if this is a system |
437 // level install. See HandleNonInstallCmdLineOptions(). | 611 // level install. See HandleNonInstallCmdLineOptions(). |
438 for (size_t i = 0; i < products.size(); ++i) { | 612 for (size_t i = 0; i < products.size(); ++i) { |
439 const Product* product = products[i]; | 613 const Product* product = products[i]; |
440 product->distribution()->LaunchUserExperiment(install_status, | 614 product->distribution()->LaunchUserExperiment(install_status, |
441 *installer_version, *product, installation.system_level()); | 615 *installer_version, *product, system_install); |
442 } | 616 } |
443 } | 617 } |
444 | 618 |
445 // Delete temporary files. These include install temporary directory | 619 // Delete temporary files. These include install temporary directory |
446 // and master profile file if present. Note that we do not care about rollback | 620 // and master profile file if present. Note that we do not care about rollback |
447 // here and we schedule for deletion on reboot below if the deletes fail. As | 621 // here and we schedule for deletion on reboot below if the deletes fail. As |
448 // such, we do not use DeleteTreeWorkItem. | 622 // such, we do not use DeleteTreeWorkItem. |
449 VLOG(1) << "Deleting temporary directory " << temp_path.value(); | 623 VLOG(1) << "Deleting temporary directory " << temp_path.value(); |
450 bool cleanup_success = file_util::Delete(temp_path, true); | 624 bool cleanup_success = file_util::Delete(temp_path, true); |
451 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { | 625 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { |
(...skipping 13 matching lines...) Expand all Loading... | |
465 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { | 639 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { |
466 std::wstring prefs_path = cmd_line.GetSwitchValueNative( | 640 std::wstring prefs_path = cmd_line.GetSwitchValueNative( |
467 installer::switches::kInstallerData); | 641 installer::switches::kInstallerData); |
468 ScheduleDirectoryForDeletion(prefs_path.c_str()); | 642 ScheduleDirectoryForDeletion(prefs_path.c_str()); |
469 } | 643 } |
470 } | 644 } |
471 | 645 |
472 for (size_t i = 0; i < products.size(); ++i) { | 646 for (size_t i = 0; i < products.size(); ++i) { |
473 const Product* product = products[i]; | 647 const Product* product = products[i]; |
474 product->distribution()->UpdateInstallStatus( | 648 product->distribution()->UpdateInstallStatus( |
475 installer_state.system_install(), incremental_install, | 649 system_install, incremental_install, prefs.is_multi_install(), |
476 prefs.is_multi_install(), install_status); | 650 install_status); |
477 } | 651 } |
478 if (prefs.is_multi_install()) { | 652 if (installer_state->is_multi_install()) { |
479 installation.properties()->UpdateInstallStatus( | 653 installer_state->multi_package_binaries_distribution()->UpdateInstallStatus( |
480 installer_state.system_install(), incremental_install, true, | 654 system_install, incremental_install, true, install_status); |
481 install_status); | |
482 } | 655 } |
483 | 656 |
484 return install_status; | 657 return install_status; |
485 } | 658 } |
486 | 659 |
487 installer::InstallStatus UninstallProduct( | 660 installer::InstallStatus UninstallProduct( |
488 const InstallationState& original_state, | 661 const InstallationState& original_state, |
489 const InstallerState& installer_state, | 662 const InstallerState& installer_state, |
490 const CommandLine& cmd_line, | 663 const CommandLine& cmd_line, |
491 const Product& product) { | 664 const Product& product) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
532 return installer::EULA_ACCEPTED_OPT_IN; | 705 return installer::EULA_ACCEPTED_OPT_IN; |
533 } | 706 } |
534 VLOG(1) << "EULA accepted (no opt-in)"; | 707 VLOG(1) << "EULA accepted (no opt-in)"; |
535 return installer::EULA_ACCEPTED; | 708 return installer::EULA_ACCEPTED; |
536 } | 709 } |
537 | 710 |
538 // This method processes any command line options that make setup.exe do | 711 // This method processes any command line options that make setup.exe do |
539 // various tasks other than installation (renaming chrome.exe, showing eula | 712 // various tasks other than installation (renaming chrome.exe, showing eula |
540 // among others). This function returns true if any such command line option | 713 // among others). This function returns true if any such command line option |
541 // has been found and processed (so setup.exe should exit at that point). | 714 // has been found and processed (so setup.exe should exit at that point). |
542 bool HandleNonInstallCmdLineOptions(const InstallerState& installer_state, | 715 bool HandleNonInstallCmdLineOptions(const InstallationState& original_state, |
543 const CommandLine& cmd_line, | 716 const CommandLine& cmd_line, |
544 const ProductPackageMapping& installs, | 717 const InstallerState& installer_state, |
545 int* exit_code) { | 718 int* exit_code) { |
546 DCHECK(installs.products().size()); | |
547 bool handled = true; | 719 bool handled = true; |
548 // TODO(tommi): Split these checks up into functions and use a data driven | 720 // TODO(tommi): Split these checks up into functions and use a data driven |
549 // map of switch->function. | 721 // map of switch->function. |
550 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { | 722 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { |
551 installer::InstallStatus status = installer::SETUP_PATCH_FAILED; | 723 installer::InstallStatus status = installer::SETUP_PATCH_FAILED; |
552 // If --update-setup-exe command line option is given, we apply the given | 724 // If --update-setup-exe command line option is given, we apply the given |
553 // patch to current exe, and store the resulting binary in the path | 725 // patch to current exe, and store the resulting binary in the path |
554 // specified by --new-setup-exe. But we need to first unpack the file | 726 // specified by --new-setup-exe. But we need to first unpack the file |
555 // given in --update-setup-exe. | 727 // given in --update-setup-exe. |
556 FilePath temp_path; | 728 FilePath temp_path; |
(...skipping 24 matching lines...) Expand all Loading... | |
581 NULL); | 753 NULL); |
582 } | 754 } |
583 file_util::Delete(temp_path, true); | 755 file_util::Delete(temp_path, true); |
584 } else if (cmd_line.HasSwitch(installer::switches::kShowEula)) { | 756 } else if (cmd_line.HasSwitch(installer::switches::kShowEula)) { |
585 // Check if we need to show the EULA. If it is passed as a command line | 757 // Check if we need to show the EULA. If it is passed as a command line |
586 // then the dialog is shown and regardless of the outcome setup exits here. | 758 // then the dialog is shown and regardless of the outcome setup exits here. |
587 std::wstring inner_frame = | 759 std::wstring inner_frame = |
588 cmd_line.GetSwitchValueNative(installer::switches::kShowEula); | 760 cmd_line.GetSwitchValueNative(installer::switches::kShowEula); |
589 *exit_code = ShowEULADialog(inner_frame); | 761 *exit_code = ShowEULADialog(inner_frame); |
590 if (installer::EULA_REJECTED != *exit_code) | 762 if (installer::EULA_REJECTED != *exit_code) |
591 GoogleUpdateSettings::SetEULAConsent(*installs.packages()[0].get(), true); | 763 GoogleUpdateSettings::SetEULAConsent(installer_state, true); |
592 } else if (cmd_line.HasSwitch( | 764 } else if (cmd_line.HasSwitch( |
593 installer::switches::kRegisterChromeBrowser)) { | 765 installer::switches::kRegisterChromeBrowser)) { |
594 const Product* chrome_install = | 766 const Product* chrome_install = |
595 FindProduct(installs.products(), BrowserDistribution::CHROME_BROWSER); | 767 installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); |
596 DCHECK(chrome_install); | |
597 if (chrome_install) { | 768 if (chrome_install) { |
598 // If --register-chrome-browser option is specified, register all | 769 // If --register-chrome-browser option is specified, register all |
599 // Chrome protocol/file associations as well as register it as a valid | 770 // Chrome protocol/file associations as well as register it as a valid |
600 // browser for Start Menu->Internet shortcut. This option should only | 771 // browser for Start Menu->Internet shortcut. This option should only |
601 // be used when setup.exe is launched with admin rights. We do not | 772 // be used when setup.exe is launched with admin rights. We do not |
602 // make any user specific changes in this option. | 773 // make any user specific changes in this option. |
603 std::wstring chrome_exe(cmd_line.GetSwitchValueNative( | 774 std::wstring chrome_exe(cmd_line.GetSwitchValueNative( |
604 installer::switches::kRegisterChromeBrowser)); | 775 installer::switches::kRegisterChromeBrowser)); |
605 std::wstring suffix; | 776 std::wstring suffix; |
606 if (cmd_line.HasSwitch( | 777 if (cmd_line.HasSwitch( |
607 installer::switches::kRegisterChromeBrowserSuffix)) { | 778 installer::switches::kRegisterChromeBrowserSuffix)) { |
608 suffix = cmd_line.GetSwitchValueNative( | 779 suffix = cmd_line.GetSwitchValueNative( |
609 installer::switches::kRegisterChromeBrowserSuffix); | 780 installer::switches::kRegisterChromeBrowserSuffix); |
610 } | 781 } |
611 *exit_code = ShellUtil::RegisterChromeBrowser( | 782 *exit_code = ShellUtil::RegisterChromeBrowser( |
612 chrome_install->distribution(), chrome_exe, suffix, false); | 783 chrome_install->distribution(), chrome_exe, suffix, false); |
613 } else { | 784 } else { |
614 LOG(ERROR) << "Can't register browser - Chrome distribution not found"; | 785 LOG(DFATAL) << "Can't register browser - Chrome distribution not found"; |
615 *exit_code = installer::UNKNOWN_STATUS; | 786 *exit_code = installer::UNKNOWN_STATUS; |
616 } | 787 } |
617 } else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { | 788 } else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { |
618 // If --rename-chrome-exe is specified, we want to rename the executables | 789 // If --rename-chrome-exe is specified, we want to rename the executables |
619 // and exit. | 790 // and exit. |
620 const Packages& packages = installs.packages(); | 791 *exit_code = RenameChromeExecutables(installer_state); |
621 DCHECK_EQ(1U, packages.size()); | |
622 for (size_t i = 0; i < packages.size(); ++i) | |
623 *exit_code = RenameChromeExecutables(*packages[i].get()); | |
624 } else if (cmd_line.HasSwitch( | 792 } else if (cmd_line.HasSwitch( |
625 installer::switches::kRemoveChromeRegistration)) { | 793 installer::switches::kRemoveChromeRegistration)) { |
626 // This is almost reverse of --register-chrome-browser option above. | 794 // This is almost reverse of --register-chrome-browser option above. |
627 // Here we delete Chrome browser registration. This option should only | 795 // Here we delete Chrome browser registration. This option should only |
628 // be used when setup.exe is launched with admin rights. We do not | 796 // be used when setup.exe is launched with admin rights. We do not |
629 // make any user specific changes in this option. | 797 // make any user specific changes in this option. |
630 std::wstring suffix; | 798 std::wstring suffix; |
631 if (cmd_line.HasSwitch( | 799 if (cmd_line.HasSwitch( |
632 installer::switches::kRegisterChromeBrowserSuffix)) { | 800 installer::switches::kRegisterChromeBrowserSuffix)) { |
633 suffix = cmd_line.GetSwitchValueNative( | 801 suffix = cmd_line.GetSwitchValueNative( |
634 installer::switches::kRegisterChromeBrowserSuffix); | 802 installer::switches::kRegisterChromeBrowserSuffix); |
635 } | 803 } |
636 installer::InstallStatus tmp = installer::UNKNOWN_STATUS; | 804 installer::InstallStatus tmp = installer::UNKNOWN_STATUS; |
637 const Product* chrome_install = | 805 const Product* chrome_install = |
638 FindProduct(installs.products(), BrowserDistribution::CHROME_BROWSER); | 806 installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); |
639 DCHECK(chrome_install); | 807 DCHECK(chrome_install); |
640 if (chrome_install) { | 808 if (chrome_install) { |
641 installer::DeleteChromeRegistrationKeys(chrome_install->distribution(), | 809 installer::DeleteChromeRegistrationKeys(chrome_install->distribution(), |
642 HKEY_LOCAL_MACHINE, suffix, tmp); | 810 HKEY_LOCAL_MACHINE, suffix, tmp); |
643 } | 811 } |
644 *exit_code = tmp; | 812 *exit_code = tmp; |
645 } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) { | 813 } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) { |
646 // Launch the inactive user toast experiment. | 814 // Launch the inactive user toast experiment. |
647 int flavor = -1; | 815 int flavor = -1; |
648 base::StringToInt(cmd_line.GetSwitchValueNative( | 816 base::StringToInt(cmd_line.GetSwitchValueNative( |
649 installer::switches::kInactiveUserToast), &flavor); | 817 installer::switches::kInactiveUserToast), &flavor); |
650 DCHECK_NE(-1, flavor); | 818 DCHECK_NE(-1, flavor); |
651 if (flavor == -1) { | 819 if (flavor == -1) { |
652 *exit_code = installer::UNKNOWN_STATUS; | 820 *exit_code = installer::UNKNOWN_STATUS; |
653 } else { | 821 } else { |
654 const Products& products = installs.products(); | 822 const Products& products = installer_state.products(); |
655 for (size_t i = 0; i < products.size(); ++i) { | 823 for (size_t i = 0; i < products.size(); ++i) { |
656 const Product* product = products[i]; | 824 const Product* product = products[i]; |
657 BrowserDistribution* browser_dist = product->distribution(); | 825 BrowserDistribution* browser_dist = product->distribution(); |
658 browser_dist->InactiveUserToastExperiment(flavor, *product); | 826 browser_dist->InactiveUserToastExperiment(flavor, *product, |
827 installer_state.target_path()); | |
659 } | 828 } |
660 } | 829 } |
661 } else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { | 830 } else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { |
662 const Products& products = installs.products(); | 831 const Products& products = installer_state.products(); |
663 for (size_t i = 0; i < products.size(); ++i) { | 832 for (size_t i = 0; i < products.size(); ++i) { |
664 const Product* product = products[i]; | 833 const Product* product = products[i]; |
665 BrowserDistribution* browser_dist = product->distribution(); | 834 BrowserDistribution* browser_dist = product->distribution(); |
666 // We started as system-level and have been re-launched as user level | 835 // We started as system-level and have been re-launched as user level |
667 // to continue with the toast experiment. | 836 // to continue with the toast experiment. |
668 scoped_ptr<Version> installed_version( | 837 scoped_ptr<Version> installed_version( |
669 InstallUtil::GetChromeVersion(browser_dist, installs.system_level())); | 838 InstallUtil::GetChromeVersion(browser_dist, |
839 installer_state.system_install())); | |
670 browser_dist->LaunchUserExperiment(installer::REENTRY_SYS_UPDATE, | 840 browser_dist->LaunchUserExperiment(installer::REENTRY_SYS_UPDATE, |
671 *installed_version, *product, true); | 841 *installed_version, *product, true); |
672 } | 842 } |
673 } else if (cmd_line.HasSwitch( | 843 } else if (cmd_line.HasSwitch( |
674 installer::switches::kChromeFrameReadyModeOptIn)) { | 844 installer::switches::kChromeFrameReadyModeOptIn)) { |
675 *exit_code = InstallUtil::GetInstallReturnCode( | 845 *exit_code = InstallUtil::GetInstallReturnCode( |
676 installer::ChromeFrameReadyModeOptIn(installer_state, cmd_line)); | 846 installer::ChromeFrameReadyModeOptIn(original_state, installer_state)); |
677 } else if (cmd_line.HasSwitch( | 847 } else if (cmd_line.HasSwitch( |
678 installer::switches::kChromeFrameReadyModeTempOptOut)) { | 848 installer::switches::kChromeFrameReadyModeTempOptOut)) { |
679 *exit_code = InstallUtil::GetInstallReturnCode( | 849 *exit_code = InstallUtil::GetInstallReturnCode( |
680 installer::ChromeFrameReadyModeTempOptOut(cmd_line)); | 850 installer::ChromeFrameReadyModeTempOptOut(original_state, |
851 installer_state)); | |
681 } else if (cmd_line.HasSwitch( | 852 } else if (cmd_line.HasSwitch( |
682 installer::switches::kChromeFrameReadyModeEndTempOptOut)) { | 853 installer::switches::kChromeFrameReadyModeEndTempOptOut)) { |
683 *exit_code = InstallUtil::GetInstallReturnCode( | 854 *exit_code = InstallUtil::GetInstallReturnCode( |
684 installer::ChromeFrameReadyModeEndTempOptOut(cmd_line)); | 855 installer::ChromeFrameReadyModeEndTempOptOut(original_state, |
856 installer_state)); | |
685 } else { | 857 } else { |
686 handled = false; | 858 handled = false; |
687 } | 859 } |
688 | 860 |
689 return handled; | 861 return handled; |
690 } | 862 } |
691 | 863 |
692 bool ShowRebootDialog() { | 864 bool ShowRebootDialog() { |
693 // Get a token for this process. | 865 // Get a token for this process. |
694 HANDLE token; | 866 HANDLE token; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
736 return false; | 908 return false; |
737 } | 909 } |
738 initialized_ = true; | 910 initialized_ = true; |
739 return true; | 911 return true; |
740 } | 912 } |
741 | 913 |
742 private: | 914 private: |
743 bool initialized_; | 915 bool initialized_; |
744 }; | 916 }; |
745 | 917 |
746 bool PopulateInstallations(bool for_uninstall, | |
747 const MasterPreferences& prefs, | |
748 ProductPackageMapping* installations) { | |
749 DCHECK(installations); | |
750 bool success = true; | |
751 | 918 |
752 bool implicit_chrome_install = false; | |
753 bool implicit_gcf_install = false; | |
754 | 919 |
755 // See what products are already installed in multi mode. | |
756 // When we do multi installs, we must upgrade all installations in sync since | |
757 // they share the binaries. Be careful to not do this when we're uninstalling | |
758 // a product. | |
759 if (prefs.is_multi_install() && !for_uninstall) { | |
760 struct CheckInstall { | |
761 bool* installed; | |
762 BrowserDistribution::Type type; | |
763 } product_checks[] = { | |
764 {&implicit_chrome_install, BrowserDistribution::CHROME_BROWSER}, | |
765 {&implicit_gcf_install, BrowserDistribution::CHROME_FRAME}, | |
766 }; | |
767 | 920 |
768 for (size_t i = 0; i < arraysize(product_checks); ++i) { | |
769 BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( | |
770 product_checks[i].type, prefs); | |
771 *product_checks[i].installed = installer::IsInstalledAsMulti( | |
772 installations->system_level(), dist); | |
773 LOG_IF(INFO, *product_checks[i].installed) | |
774 << "Product already installed and must be included: " | |
775 << dist->GetApplicationName(); | |
776 } | |
777 } | |
778 | |
779 if (prefs.install_chrome() || implicit_chrome_install) { | |
780 VLOG(1) << (for_uninstall ? "Uninstall" : "Install") | |
781 << " distribution: Chrome"; | |
782 success = installations->AddDistribution( | |
783 BrowserDistribution::CHROME_BROWSER, prefs); | |
784 } | |
785 | |
786 if (success && (prefs.install_chrome_frame() || implicit_gcf_install)) { | |
787 VLOG(1) << (for_uninstall ? "Uninstall" : "Install") | |
788 << " distribution: Chrome Frame"; | |
789 success = installations->AddDistribution( | |
790 BrowserDistribution::CHROME_FRAME, prefs); | |
791 } | |
792 return success; | |
793 } | |
794 | 921 |
795 // Returns the Custom information for the client identified by the exe path | 922 // Returns the Custom information for the client identified by the exe path |
796 // passed in. This information is used for crash reporting. | 923 // passed in. This information is used for crash reporting. |
797 google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) { | 924 google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) { |
798 std::wstring product; | 925 std::wstring product; |
799 std::wstring version; | 926 std::wstring version; |
800 scoped_ptr<FileVersionInfo> | 927 scoped_ptr<FileVersionInfo> |
801 version_info(FileVersionInfo::CreateFileVersionInfo(FilePath(exe_path))); | 928 version_info(FileVersionInfo::CreateFileVersionInfo(FilePath(exe_path))); |
802 if (version_info.get()) { | 929 if (version_info.get()) { |
803 version = version_info->product_version(); | 930 version = version_info->product_version(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
876 | 1003 |
877 VLOG(1) << "multi install is " << prefs.is_multi_install(); | 1004 VLOG(1) << "multi install is " << prefs.is_multi_install(); |
878 bool system_install = false; | 1005 bool system_install = false; |
879 prefs.GetBool(installer::master_preferences::kSystemLevel, &system_install); | 1006 prefs.GetBool(installer::master_preferences::kSystemLevel, &system_install); |
880 VLOG(1) << "system install is " << system_install; | 1007 VLOG(1) << "system install is " << system_install; |
881 | 1008 |
882 google_breakpad::scoped_ptr<google_breakpad::ExceptionHandler> breakpad( | 1009 google_breakpad::scoped_ptr<google_breakpad::ExceptionHandler> breakpad( |
883 InitializeCrashReporting(system_install)); | 1010 InitializeCrashReporting(system_install)); |
884 | 1011 |
885 InstallationState original_state; | 1012 InstallationState original_state; |
886 original_state.Initialize(prefs); | 1013 original_state.Initialize(); |
887 | 1014 |
888 InstallerState installer_state; | 1015 InstallerState installer_state; |
889 installer_state.Initialize(prefs, original_state); | 1016 installer_state.Initialize(cmd_line, prefs, original_state); |
890 const bool is_uninstall = cmd_line.HasSwitch(installer::switches::kUninstall); | 1017 const bool is_uninstall = cmd_line.HasSwitch(installer::switches::kUninstall); |
891 | 1018 |
892 ProductPackageMapping installations(prefs.is_multi_install(), system_install); | |
893 if (!PopulateInstallations(is_uninstall, prefs, &installations)) { | |
894 // Currently this can only fail if one of the installations is a multi and | |
895 // a pre-existing single installation exists or vice versa. | |
896 installer::InstallStatus status = installer::NON_MULTI_INSTALLATION_EXISTS; | |
897 int string_id = IDS_INSTALL_NON_MULTI_INSTALLATION_EXISTS_BASE; | |
898 if (!prefs.is_multi_install()) { | |
899 status = installer::MULTI_INSTALLATION_EXISTS; | |
900 string_id = IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE; | |
901 } | |
902 LOG(ERROR) << "Failed to populate installations: " << status; | |
903 InstallUtil::WriteInstallerResult(system_install, | |
904 installer_state.state_key(), status, string_id, NULL); | |
905 return status; | |
906 } | |
907 | |
908 // Check to make sure current system is WinXP or later. If not, log | 1019 // Check to make sure current system is WinXP or later. If not, log |
909 // error message and get out. | 1020 // error message and get out. |
910 if (!InstallUtil::IsOSSupported()) { | 1021 if (!InstallUtil::IsOSSupported()) { |
911 LOG(ERROR) << "Chrome only supports Windows XP or later."; | 1022 LOG(ERROR) << "Chrome only supports Windows XP or later."; |
912 InstallUtil::WriteInstallerResult(system_install, | 1023 InstallUtil::WriteInstallerResult(system_install, |
913 installer_state.state_key(), installer::OS_NOT_SUPPORTED, | 1024 installer_state.state_key(), installer::OS_NOT_SUPPORTED, |
914 IDS_INSTALL_OS_NOT_SUPPORTED_BASE, NULL); | 1025 IDS_INSTALL_OS_NOT_SUPPORTED_BASE, NULL); |
915 return installer::OS_NOT_SUPPORTED; | 1026 return installer::OS_NOT_SUPPORTED; |
916 } | 1027 } |
917 | 1028 |
(...skipping 15 matching lines...) Expand all Loading... | |
933 cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser) || | 1044 cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser) || |
934 cmd_line.HasSwitch( | 1045 cmd_line.HasSwitch( |
935 installer::switches::kRemoveChromeRegistration) || | 1046 installer::switches::kRemoveChromeRegistration) || |
936 cmd_line.HasSwitch(installer::switches::kInactiveUserToast) || | 1047 cmd_line.HasSwitch(installer::switches::kInactiveUserToast) || |
937 cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { | 1048 cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { |
938 return installer::SXS_OPTION_NOT_SUPPORTED; | 1049 return installer::SXS_OPTION_NOT_SUPPORTED; |
939 } | 1050 } |
940 } | 1051 } |
941 | 1052 |
942 int exit_code = 0; | 1053 int exit_code = 0; |
943 if (HandleNonInstallCmdLineOptions(installer_state, cmd_line, installations, | 1054 if (HandleNonInstallCmdLineOptions(original_state, cmd_line, installer_state, |
944 &exit_code)) | 1055 &exit_code)) |
945 return exit_code; | 1056 return exit_code; |
946 | 1057 |
947 if (system_install && !IsUserAnAdmin()) { | 1058 if (system_install && !IsUserAnAdmin()) { |
948 if (base::win::GetVersion() >= base::win::VERSION_VISTA && | 1059 if (base::win::GetVersion() >= base::win::VERSION_VISTA && |
949 !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { | 1060 !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { |
950 CommandLine new_cmd(CommandLine::NO_PROGRAM); | 1061 CommandLine new_cmd(CommandLine::NO_PROGRAM); |
951 new_cmd.AppendArguments(cmd_line, true); | 1062 new_cmd.AppendArguments(cmd_line, true); |
952 // Append --run-as-admin flag to let the new instance of setup.exe know | 1063 // Append --run-as-admin flag to let the new instance of setup.exe know |
953 // that we already tried to launch ourselves as admin. | 1064 // that we already tried to launch ourselves as admin. |
954 new_cmd.AppendSwitch(installer::switches::kRunAsAdmin); | 1065 new_cmd.AppendSwitch(installer::switches::kRunAsAdmin); |
955 DWORD exit_code = installer::UNKNOWN_STATUS; | 1066 DWORD exit_code = installer::UNKNOWN_STATUS; |
956 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); | 1067 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); |
957 return exit_code; | 1068 return exit_code; |
958 } else { | 1069 } else { |
959 LOG(ERROR) << "Non admin user can not install system level Chrome."; | 1070 LOG(ERROR) << "Non admin user can not install system level Chrome."; |
960 InstallUtil::WriteInstallerResult(system_install, | 1071 InstallUtil::WriteInstallerResult(system_install, |
961 installer_state.state_key(), installer::INSUFFICIENT_RIGHTS, | 1072 installer_state.state_key(), installer::INSUFFICIENT_RIGHTS, |
962 IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE, NULL); | 1073 IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE, NULL); |
963 return installer::INSUFFICIENT_RIGHTS; | 1074 return installer::INSUFFICIENT_RIGHTS; |
964 } | 1075 } |
965 } | 1076 } |
966 | 1077 |
967 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | 1078 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; |
968 // If --uninstall option is given, uninstall chrome | 1079 // If --uninstall option is given, uninstall the identified product(s) |
969 if (is_uninstall) { | 1080 if (is_uninstall) { |
970 for (size_t i = 0; i < installations.products().size(); ++i) { | 1081 const Products& products = installer_state.products(); |
1082 for (size_t i = 0; i < products.size(); ++i) { | |
971 install_status = UninstallProduct(original_state, installer_state, | 1083 install_status = UninstallProduct(original_state, installer_state, |
972 cmd_line, *installations.products()[i]); | 1084 cmd_line, *products[i]); |
973 } | 1085 } |
974 } else { | 1086 } else { |
975 // If --uninstall option is not specified, we assume it is install case. | 1087 // If --uninstall option is not specified, we assume it is install case. |
976 const Packages& packages = installations.packages(); | 1088 VLOG(1) << "Installing to " << installer_state.target_path().value(); |
977 VLOG(1) << "Installing to " << packages.size() << " target paths"; | 1089 install_status = InstallProducts(original_state, cmd_line, prefs, |
978 for (size_t i = 0; i < packages.size(); ++i) { | 1090 &installer_state); |
979 install_status = InstallChrome(original_state, installer_state, cmd_line, | |
980 *packages[i].get(), prefs); | |
981 } | |
982 } | 1091 } |
983 | 1092 |
984 const Product* cf_install = | 1093 const Product* cf_install = |
985 FindProduct(installations.products(), BrowserDistribution::CHROME_FRAME); | 1094 installer_state.FindProduct(BrowserDistribution::CHROME_FRAME); |
986 | 1095 |
987 if (cf_install && | 1096 if (cf_install && |
988 !cmd_line.HasSwitch(installer::switches::kForceUninstall)) { | 1097 !cmd_line.HasSwitch(installer::switches::kForceUninstall)) { |
989 if (install_status == installer::UNINSTALL_REQUIRES_REBOOT) { | 1098 if (install_status == installer::UNINSTALL_REQUIRES_REBOOT) { |
990 ShowRebootDialog(); | 1099 ShowRebootDialog(); |
991 } else if (is_uninstall) { | 1100 } else if (is_uninstall) { |
992 // Only show the message box if Chrome Frame was the only product being | 1101 // Only show the message box if Chrome Frame was the only product being |
993 // uninstalled. | 1102 // uninstalled. |
994 if (installations.products().size() == 1U) { | 1103 if (installer_state.products().size() == 1U) { |
995 ::MessageBoxW(NULL, | 1104 ::MessageBoxW(NULL, |
996 installer::GetLocalizedString( | 1105 installer::GetLocalizedString( |
997 IDS_UNINSTALL_COMPLETE_BASE).c_str(), | 1106 IDS_UNINSTALL_COMPLETE_BASE).c_str(), |
998 cf_install->distribution()->GetApplicationName().c_str(), | 1107 cf_install->distribution()->GetApplicationName().c_str(), |
999 MB_OK); | 1108 MB_OK); |
1000 } | 1109 } |
1001 } | 1110 } |
1002 } | 1111 } |
1003 | 1112 |
1004 int return_code = 0; | 1113 int return_code = 0; |
1005 // MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will | 1114 // MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will |
1006 // rollback the action. If we're uninstalling we want to avoid this, so always | 1115 // rollback the action. If we're uninstalling we want to avoid this, so always |
1007 // report success, squashing any more informative return codes. | 1116 // report success, squashing any more informative return codes. |
1008 // TODO(tommi): Fix this loop when IsMsi has been moved out of the Product | 1117 if (!(installer_state.is_msi() && is_uninstall)) |
1009 // class. | 1118 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT |
1010 for (size_t i = 0; i < installations.products().size(); ++i) { | 1119 // to pass through, since this is only returned on uninstall which is |
1011 const Product* product = installations.products()[i]; | 1120 // never invoked directly by Google Update. |
1012 if (!(product->IsMsi() && is_uninstall)) { | 1121 return_code = InstallUtil::GetInstallReturnCode(install_status); |
1013 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT | |
1014 // to pass through, since this is only returned on uninstall which is | |
1015 // never invoked directly by Google Update. | |
1016 return_code = InstallUtil::GetInstallReturnCode(install_status); | |
1017 } | |
1018 } | |
1019 | 1122 |
1020 VLOG(1) << "Installation complete, returning: " << return_code; | 1123 VLOG(1) << "Installation complete, returning: " << return_code; |
1021 | 1124 |
1022 return return_code; | 1125 return return_code; |
1023 } | 1126 } |
OLD | NEW |