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

Side by Side Diff: chrome/installer/setup/setup_main.cc

Issue 6288009: More installer refactoring in the interest of fixing some bugs and cleaning t... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698