OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 <shlobj.h> | 5 #include <shlobj.h> |
6 #include <time.h> | 6 #include <time.h> |
7 | 7 |
8 #include "chrome/installer/setup/install.h" | 8 #include "chrome/installer/setup/install.h" |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 uninstall_cmd_line->append(installer_util::switches::kDeleteProfile); | 92 uninstall_cmd_line->append(installer_util::switches::kDeleteProfile); |
93 uninstall_cmd_line->append(L" --"); | 93 uninstall_cmd_line->append(L" --"); |
94 uninstall_cmd_line->append(installer_util::switches::kChromeFrame); | 94 uninstall_cmd_line->append(installer_util::switches::kChromeFrame); |
95 } | 95 } |
96 | 96 |
97 if (InstallUtil::IsChromeSxSProcess()) { | 97 if (InstallUtil::IsChromeSxSProcess()) { |
98 uninstall_cmd_line->append(L" --"); | 98 uninstall_cmd_line->append(L" --"); |
99 uninstall_cmd_line->append(installer_util::switches::kChromeSxS); | 99 uninstall_cmd_line->append(installer_util::switches::kChromeSxS); |
100 } | 100 } |
101 | 101 |
102 if (InstallUtil::IsMSIProcess()) { | 102 if (InstallUtil::IsMSIProcess(is_system)) { |
103 uninstall_cmd_line->append(L" --"); | 103 uninstall_cmd_line->append(L" --"); |
104 uninstall_cmd_line->append(installer_util::switches::kMsi); | 104 uninstall_cmd_line->append(installer_util::switches::kMsi); |
105 } | 105 } |
106 | 106 |
107 // Propagate the verbose logging switch to uninstalls too. | 107 // Propagate the verbose logging switch to uninstalls too. |
108 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 108 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
109 if (command_line.HasSwitch(installer_util::switches::kVerboseLogging)) { | 109 if (command_line.HasSwitch(installer_util::switches::kVerboseLogging)) { |
110 uninstall_cmd_line->append(L" --"); | 110 uninstall_cmd_line->append(L" --"); |
111 uninstall_cmd_line->append(installer_util::switches::kVerboseLogging); | 111 uninstall_cmd_line->append(installer_util::switches::kVerboseLogging); |
112 } | 112 } |
113 | 113 |
114 if (is_system) { | 114 if (is_system) { |
115 uninstall_cmd_line->append(L" --"); | 115 uninstall_cmd_line->append(L" --"); |
116 uninstall_cmd_line->append(installer_util::switches::kSystemLevel); | 116 uninstall_cmd_line->append(installer_util::switches::kSystemLevel); |
117 } | 117 } |
118 } | 118 } |
119 | 119 |
120 // This method adds work items to create (or update) Chrome uninstall entry in | 120 // This method adds work items to create (or update) Chrome uninstall entry in |
121 // either the Control Panel->Add/Remove Programs list or in the Omaha client | 121 // either the Control Panel->Add/Remove Programs list or in the Omaha client |
122 // state key if running under an MSI installer. | 122 // state key if running under an MSI installer. |
123 void AddUninstallShortcutWorkItems(HKEY reg_root, | 123 void AddUninstallShortcutWorkItems(HKEY reg_root, |
124 const std::wstring& exe_path, | 124 const std::wstring& exe_path, |
125 const std::wstring& install_path, | 125 const std::wstring& install_path, |
126 const std::wstring& product_name, | 126 const std::wstring& product_name, |
127 const std::wstring& new_version, | 127 const std::wstring& new_version, |
128 WorkItemList* install_list) { | 128 WorkItemList* install_list) { |
129 std::wstring uninstall_cmd(L"\""); | |
130 uninstall_cmd.append(installer::GetInstallerPathUnderChrome(install_path, | |
131 new_version)); | |
132 file_util::AppendToPath(&uninstall_cmd, | |
133 file_util::GetFilenameFromPath(exe_path)); | |
134 uninstall_cmd.append(L"\""); | |
135 | |
136 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 129 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
137 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 130 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
138 | 131 |
139 | |
140 // When we are installed via an MSI, we need to store our uninstall strings | 132 // When we are installed via an MSI, we need to store our uninstall strings |
141 // in the Google Update client state key. We do this even for non-MSI | 133 // in the Google Update client state key. We do this even for non-MSI |
142 // managed installs to avoid breaking the edge case whereby an MSI-managed | 134 // managed installs to avoid breaking the edge case whereby an MSI-managed |
143 // install is updated by a non-msi installer (which would confuse the MSI | 135 // install is updated by a non-msi installer (which would confuse the MSI |
144 // machinery if these strings were not also updated). | 136 // machinery if these strings were not also updated). |
| 137 // Do not quote the command line for the MSI invocation. |
| 138 std::wstring uninstall_cmd( |
| 139 installer::GetInstallerPathUnderChrome(install_path, new_version)); |
| 140 file_util::AppendToPath(&uninstall_cmd, |
| 141 file_util::GetFilenameFromPath(exe_path)); |
145 std::wstring uninstall_arguments; | 142 std::wstring uninstall_arguments; |
146 AppendUninstallCommandLineFlags(&uninstall_arguments, | 143 AppendUninstallCommandLineFlags(&uninstall_arguments, |
147 reg_root == HKEY_LOCAL_MACHINE); | 144 reg_root == HKEY_LOCAL_MACHINE); |
| 145 |
148 std::wstring update_state_key = dist->GetStateKey(); | 146 std::wstring update_state_key = dist->GetStateKey(); |
149 install_list->AddCreateRegKeyWorkItem(reg_root, update_state_key); | 147 install_list->AddCreateRegKeyWorkItem(reg_root, update_state_key); |
150 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, | 148 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, |
151 installer_util::kUninstallStringField, uninstall_cmd, true); | 149 installer_util::kUninstallStringField, uninstall_cmd, true); |
152 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, | 150 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, |
153 installer_util::kUninstallArgumentsField, uninstall_arguments, true); | 151 installer_util::kUninstallArgumentsField, uninstall_arguments, true); |
154 | 152 |
155 // MSI installations will manage their own uninstall shortcuts. | 153 // MSI installations will manage their own uninstall shortcuts. |
156 if (!InstallUtil::IsMSIProcess()) { | 154 if (!InstallUtil::IsMSIProcess(reg_root == HKEY_LOCAL_MACHINE)) { |
157 AppendUninstallCommandLineFlags(&uninstall_cmd, | 155 // We need to quote the command line for the Add/Remove Programs dialog. |
| 156 std::wstring quoted_uninstall_cmd(L"\""); |
| 157 quoted_uninstall_cmd += uninstall_cmd; |
| 158 quoted_uninstall_cmd += L"\""; |
| 159 |
| 160 AppendUninstallCommandLineFlags("ed_uninstall_cmd, |
158 reg_root == HKEY_LOCAL_MACHINE); | 161 reg_root == HKEY_LOCAL_MACHINE); |
159 std::wstring uninstall_reg = dist->GetUninstallRegPath(); | 162 std::wstring uninstall_reg = dist->GetUninstallRegPath(); |
160 install_list->AddCreateRegKeyWorkItem(reg_root, uninstall_reg); | 163 install_list->AddCreateRegKeyWorkItem(reg_root, uninstall_reg); |
161 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, | 164 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, |
162 installer_util::kUninstallDisplayNameField, product_name, true); | 165 installer_util::kUninstallDisplayNameField, product_name, true); |
163 install_list->AddSetRegValueWorkItem(reg_root, | 166 install_list->AddSetRegValueWorkItem(reg_root, |
164 uninstall_reg, | 167 uninstall_reg, |
165 installer_util::kUninstallStringField, | 168 installer_util::kUninstallStringField, |
166 uninstall_cmd, true); | 169 quoted_uninstall_cmd, |
| 170 true); |
167 install_list->AddSetRegValueWorkItem(reg_root, | 171 install_list->AddSetRegValueWorkItem(reg_root, |
168 uninstall_reg, | 172 uninstall_reg, |
169 L"InstallLocation", | 173 L"InstallLocation", |
170 install_path, | 174 install_path, |
171 true); | 175 true); |
172 | 176 |
173 // DisplayIcon, NoModify and NoRepair | 177 // DisplayIcon, NoModify and NoRepair |
174 std::wstring chrome_icon = AppendPath(install_path, | 178 std::wstring chrome_icon = AppendPath(install_path, |
175 installer_util::kChromeExe); | 179 installer_util::kChromeExe); |
176 ShellUtil::GetChromeIcon(chrome_icon); | 180 ShellUtil::GetChromeIcon(chrome_icon); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 chrome_link.value(), | 279 chrome_link.value(), |
276 product_desc, true); | 280 product_desc, true); |
277 } else if (file_util::PathExists(chrome_link)) { | 281 } else if (file_util::PathExists(chrome_link)) { |
278 LOG(INFO) << "Updating shortcut at " << chrome_link.value() | 282 LOG(INFO) << "Updating shortcut at " << chrome_link.value() |
279 << " to point to " << chrome_exe; | 283 << " to point to " << chrome_exe; |
280 ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, | 284 ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, |
281 chrome_link.value(), | 285 chrome_link.value(), |
282 product_desc, false); | 286 product_desc, false); |
283 } | 287 } |
284 | 288 |
285 // Create/update uninstall link | 289 // Create/update uninstall link if we are not an MSI install. MSI |
286 FilePath uninstall_link(shortcut_path); // Uninstall Chrome link | 290 // installations are, for the time being, managed only through the |
287 uninstall_link = uninstall_link.Append( | 291 // Add/Remove Programs dialog. |
288 dist->GetUninstallLinkName() + L".lnk"); | 292 // TODO(robertshield): We could add a shortcut to msiexec /X {GUID} here. |
289 if ((install_status == installer_util::FIRST_INSTALL_SUCCESS) || | 293 if (!InstallUtil::IsMSIProcess(system_install)) { |
290 (install_status == installer_util::INSTALL_REPAIRED) || | 294 FilePath uninstall_link(shortcut_path); // Uninstall Chrome link |
291 (file_util::PathExists(uninstall_link))) { | 295 uninstall_link = uninstall_link.Append( |
292 if (!file_util::PathExists(shortcut_path)) | 296 dist->GetUninstallLinkName() + L".lnk"); |
293 file_util::CreateDirectoryW(shortcut_path); | 297 if ((install_status == installer_util::FIRST_INSTALL_SUCCESS) || |
294 std::wstring setup_exe(installer::GetInstallerPathUnderChrome(install_path, | 298 (install_status == installer_util::INSTALL_REPAIRED) || |
295 new_version)); | 299 (file_util::PathExists(uninstall_link))) { |
296 file_util::AppendToPath(&setup_exe, | 300 if (!file_util::PathExists(shortcut_path)) |
297 file_util::GetFilenameFromPath(exe_path)); | 301 file_util::CreateDirectoryW(shortcut_path); |
| 302 std::wstring setup_exe(installer::GetInstallerPathUnderChrome( |
| 303 install_path, new_version)); |
| 304 file_util::AppendToPath(&setup_exe, |
| 305 file_util::GetFilenameFromPath(exe_path)); |
298 | 306 |
299 std::wstring arguments; | 307 std::wstring arguments; |
300 AppendUninstallCommandLineFlags(&arguments, system_install); | 308 AppendUninstallCommandLineFlags(&arguments, system_install); |
301 | 309 LOG(INFO) << "Creating/updating uninstall link at " |
302 LOG(INFO) << "Creating/updating uninstall link at " | 310 << uninstall_link.value(); |
303 << uninstall_link.value(); | 311 ret = ret && file_util::CreateShortcutLink(setup_exe.c_str(), |
304 ret = ret && file_util::CreateShortcutLink(setup_exe.c_str(), | 312 uninstall_link.value().c_str(), |
305 uninstall_link.value().c_str(), | 313 NULL, |
306 NULL, | 314 arguments.c_str(), |
307 arguments.c_str(), | 315 NULL, |
308 NULL, setup_exe.c_str(), 0, | 316 setup_exe.c_str(), |
309 NULL); | 317 0, |
| 318 NULL); |
| 319 } |
310 } | 320 } |
311 | 321 |
312 // Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts | 322 // Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts |
313 // is specified we want to create them, otherwise we update them only if | 323 // is specified we want to create them, otherwise we update them only if |
314 // they exist. | 324 // they exist. |
315 if (system_install) { | 325 if (system_install) { |
316 ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, | 326 ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, |
317 product_desc, ShellUtil::SYSTEM_LEVEL, alt_shortcut, | 327 product_desc, ShellUtil::SYSTEM_LEVEL, alt_shortcut, |
318 create_all_shortcut); | 328 create_all_shortcut); |
319 ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, | 329 ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, |
320 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, create_all_shortcut); | 330 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, create_all_shortcut); |
321 } else { | 331 } else { |
322 ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, | 332 ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, |
323 product_desc, ShellUtil::CURRENT_USER, alt_shortcut, | 333 product_desc, ShellUtil::CURRENT_USER, alt_shortcut, |
324 create_all_shortcut); | 334 create_all_shortcut); |
325 ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, | 335 ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, |
326 ShellUtil::CURRENT_USER, create_all_shortcut); | 336 ShellUtil::CURRENT_USER, create_all_shortcut); |
327 } | 337 } |
328 | 338 |
329 return ret; | 339 return ret; |
330 } | 340 } |
331 | 341 |
332 // After a successful copying of all the files, this function is called to | 342 // After a successful copying of all the files, this function is called to |
333 // do a few post install tasks: | 343 // do a few post install tasks: |
334 // - Handle the case of in-use-update by updating "opv" key or deleting it if | 344 // - Handle the case of in-use-update by updating "opv" key or deleting it if |
335 // not required. | 345 // not required. |
336 // - Register any new dlls and unregister old dlls. | 346 // - Register any new dlls and unregister old dlls. |
| 347 // - If this is an MSI install, ensures that the MSI marker is set, and sets |
| 348 // it if not. |
337 // If these operations are successful, the function returns true, otherwise | 349 // If these operations are successful, the function returns true, otherwise |
338 // false. | 350 // false. |
339 bool DoPostInstallTasks(HKEY reg_root, | 351 bool DoPostInstallTasks(HKEY reg_root, |
340 const std::wstring& exe_path, | 352 const std::wstring& exe_path, |
341 const std::wstring& install_path, | 353 const std::wstring& install_path, |
342 const std::wstring& new_chrome_exe, | 354 const std::wstring& new_chrome_exe, |
343 const std::wstring& current_version, | 355 const std::wstring& current_version, |
344 const installer::Version& new_version) { | 356 const installer::Version& new_version) { |
345 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 357 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
346 std::wstring version_key = dist->GetVersionKey(); | 358 std::wstring version_key = dist->GetVersionKey(); |
347 | 359 |
| 360 bool is_system_install = (reg_root == HKEY_LOCAL_MACHINE); |
| 361 |
348 if (file_util::PathExists(FilePath::FromWStringHack(new_chrome_exe))) { | 362 if (file_util::PathExists(FilePath::FromWStringHack(new_chrome_exe))) { |
349 // Looks like this was in use update. So make sure we update the 'opv' key | 363 // Looks like this was in use update. So make sure we update the 'opv' key |
350 // with the current version that is active and 'cmd' key with the rename | 364 // with the current version that is active and 'cmd' key with the rename |
351 // command to run. | 365 // command to run. |
352 if (current_version.empty()) { | 366 if (current_version.empty()) { |
353 LOG(ERROR) << "New chrome.exe exists but current version is empty!"; | 367 LOG(ERROR) << "New chrome.exe exists but current version is empty!"; |
354 return false; | 368 return false; |
355 } | 369 } |
356 scoped_ptr<WorkItemList> inuse_list(WorkItem::CreateWorkItemList()); | 370 scoped_ptr<WorkItemList> inuse_list(WorkItem::CreateWorkItemList()); |
357 inuse_list->AddSetRegValueWorkItem(reg_root, | 371 inuse_list->AddSetRegValueWorkItem(reg_root, |
358 version_key, | 372 version_key, |
359 google_update::kRegOldVersionField, | 373 google_update::kRegOldVersionField, |
360 current_version.c_str(), | 374 current_version.c_str(), |
361 true); | 375 true); |
362 | 376 |
363 std::wstring rename_cmd(installer::GetInstallerPathUnderChrome( | 377 std::wstring rename_cmd(installer::GetInstallerPathUnderChrome( |
364 install_path, new_version.GetString())); | 378 install_path, new_version.GetString())); |
365 file_util::AppendToPath(&rename_cmd, | 379 file_util::AppendToPath(&rename_cmd, |
366 file_util::GetFilenameFromPath(exe_path)); | 380 file_util::GetFilenameFromPath(exe_path)); |
367 rename_cmd = L"\"" + rename_cmd + | 381 rename_cmd = L"\"" + rename_cmd + |
368 L"\" --" + installer_util::switches::kRenameChromeExe; | 382 L"\" --" + installer_util::switches::kRenameChromeExe; |
369 if (reg_root == HKEY_LOCAL_MACHINE) | 383 if (is_system_install) |
370 rename_cmd = rename_cmd + L" --" + installer_util::switches::kSystemLevel; | 384 rename_cmd = rename_cmd + L" --" + installer_util::switches::kSystemLevel; |
371 | 385 |
372 if (InstallUtil::IsChromeFrameProcess()) { | 386 if (InstallUtil::IsChromeFrameProcess()) { |
373 rename_cmd += L" --"; | 387 rename_cmd += L" --"; |
374 rename_cmd += installer_util::switches::kChromeFrame; | 388 rename_cmd += installer_util::switches::kChromeFrame; |
375 } | 389 } |
376 | 390 |
377 if (InstallUtil::IsChromeSxSProcess()) { | 391 if (InstallUtil::IsChromeSxSProcess()) { |
378 rename_cmd += L" --"; | 392 rename_cmd += L" --"; |
379 rename_cmd += installer_util::switches::kChromeSxS; | 393 rename_cmd += installer_util::switches::kChromeSxS; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 if (InstallUtil::BuildDLLRegistrationList(dll_path, kDllsToRegister, | 448 if (InstallUtil::BuildDLLRegistrationList(dll_path, kDllsToRegister, |
435 kNumDllsToRegister, true, | 449 kNumDllsToRegister, true, |
436 dll_list.get())) { | 450 dll_list.get())) { |
437 if (!dll_list->Do()) { | 451 if (!dll_list->Do()) { |
438 dll_list->Rollback(); | 452 dll_list->Rollback(); |
439 return false; | 453 return false; |
440 } | 454 } |
441 } | 455 } |
442 } | 456 } |
443 | 457 |
| 458 // If we're told that we're an MSI install, make sure to set the marker |
| 459 // in the client state key so that future updates do the right thing. |
| 460 if (InstallUtil::IsMSIProcess(is_system_install)) { |
| 461 if (!InstallUtil::SetMSIMarker(is_system_install, true)) |
| 462 return false; |
| 463 } |
| 464 |
444 return true; | 465 return true; |
445 } | 466 } |
446 | 467 |
447 // This method tells if we are running on 64 bit platform so that we can copy | 468 // This method tells if we are running on 64 bit platform so that we can copy |
448 // one extra exe. If the API call to determine 64 bit fails, we play it safe | 469 // one extra exe. If the API call to determine 64 bit fails, we play it safe |
449 // and return true anyway so that the executable can be copied. | 470 // and return true anyway so that the executable can be copied. |
450 bool Is64bit() { | 471 bool Is64bit() { |
451 typedef BOOL (WINAPI *WOW_FUNC)(HANDLE, PBOOL); | 472 typedef BOOL (WINAPI *WOW_FUNC)(HANDLE, PBOOL); |
452 BOOL is64 = FALSE; | 473 BOOL is64 = FALSE; |
453 | 474 |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 } | 735 } |
715 | 736 |
716 std::wstring latest_version_to_keep(new_version.GetString()); | 737 std::wstring latest_version_to_keep(new_version.GetString()); |
717 if (!current_version.empty()) | 738 if (!current_version.empty()) |
718 latest_version_to_keep.assign(current_version); | 739 latest_version_to_keep.assign(current_version); |
719 RemoveOldVersionDirs(install_path, latest_version_to_keep); | 740 RemoveOldVersionDirs(install_path, latest_version_to_keep); |
720 } | 741 } |
721 | 742 |
722 return result; | 743 return result; |
723 } | 744 } |
OLD | NEW |