| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // This file defines the methods useful for uninstalling Chrome. | 5 // This file defines the methods useful for uninstalling Chrome. |
| 6 | 6 |
| 7 #include "chrome/installer/setup/uninstall.h" | 7 #include "chrome/installer/setup/uninstall.h" |
| 8 | 8 |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "chrome/installer/util/install_util.h" | 25 #include "chrome/installer/util/install_util.h" |
| 26 #include "chrome/installer/util/logging_installer.h" | 26 #include "chrome/installer/util/logging_installer.h" |
| 27 #include "chrome/installer/util/shell_util.h" | 27 #include "chrome/installer/util/shell_util.h" |
| 28 #include "chrome/installer/util/util_constants.h" | 28 #include "chrome/installer/util/util_constants.h" |
| 29 #include "chrome/installer/util/version.h" | 29 #include "chrome/installer/util/version.h" |
| 30 | 30 |
| 31 // Build-time generated include file. | 31 // Build-time generated include file. |
| 32 #include "registered_dlls.h" // NOLINT | 32 #include "registered_dlls.h" // NOLINT |
| 33 | 33 |
| 34 using base::win::RegKey; | 34 using base::win::RegKey; |
| 35 using installer_util::InstallStatus; | 35 using installer::InstallStatus; |
| 36 | 36 |
| 37 namespace installer { | 37 namespace installer { |
| 38 | 38 |
| 39 // This functions checks for any Chrome instances that are | 39 // This functions checks for any Chrome instances that are |
| 40 // running and first asks them to close politely by sending a Windows message. | 40 // running and first asks them to close politely by sending a Windows message. |
| 41 // If there is an error while sending message or if there are still Chrome | 41 // If there is an error while sending message or if there are still Chrome |
| 42 // procesess active after the message has been sent, this function will try | 42 // procesess active after the message has been sent, this function will try |
| 43 // to kill them. | 43 // to kill them. |
| 44 void CloseAllChromeProcesses() { | 44 void CloseAllChromeProcesses() { |
| 45 for (int j = 0; j < 4; ++j) { | 45 for (int j = 0; j < 4; ++j) { |
| 46 std::wstring wnd_class(L"Chrome_WidgetWin_"); | 46 std::wstring wnd_class(L"Chrome_WidgetWin_"); |
| 47 wnd_class.append(base::IntToString16(j)); | 47 wnd_class.append(base::IntToString16(j)); |
| 48 HWND window = FindWindowEx(NULL, NULL, wnd_class.c_str(), NULL); | 48 HWND window = FindWindowEx(NULL, NULL, wnd_class.c_str(), NULL); |
| 49 while (window) { | 49 while (window) { |
| 50 HWND tmpWnd = window; | 50 HWND tmpWnd = window; |
| 51 window = FindWindowEx(NULL, window, wnd_class.c_str(), NULL); | 51 window = FindWindowEx(NULL, window, wnd_class.c_str(), NULL); |
| 52 if (!SendMessageTimeout(tmpWnd, WM_CLOSE, 0, 0, SMTO_BLOCK, 3000, NULL) && | 52 if (!SendMessageTimeout(tmpWnd, WM_CLOSE, 0, 0, SMTO_BLOCK, 3000, NULL) && |
| 53 (GetLastError() == ERROR_TIMEOUT)) { | 53 (GetLastError() == ERROR_TIMEOUT)) { |
| 54 base::CleanupProcesses(installer_util::kChromeExe, 0, | 54 base::CleanupProcesses(installer::kChromeExe, 0, |
| 55 ResultCodes::HUNG, NULL); | 55 ResultCodes::HUNG, NULL); |
| 56 base::CleanupProcesses(installer_util::kNaClExe, 0, | 56 base::CleanupProcesses(installer::kNaClExe, 0, |
| 57 ResultCodes::HUNG, NULL); | 57 ResultCodes::HUNG, NULL); |
| 58 return; | 58 return; |
| 59 } | 59 } |
| 60 } | 60 } |
| 61 } | 61 } |
| 62 | 62 |
| 63 // If asking politely didn't work, wait for 15 seconds and then kill all | 63 // If asking politely didn't work, wait for 15 seconds and then kill all |
| 64 // chrome.exe. This check is just in case Chrome is ignoring WM_CLOSE | 64 // chrome.exe. This check is just in case Chrome is ignoring WM_CLOSE |
| 65 // messages. | 65 // messages. |
| 66 base::CleanupProcesses(installer_util::kChromeExe, 15000, | 66 base::CleanupProcesses(installer::kChromeExe, 15000, |
| 67 ResultCodes::HUNG, NULL); | 67 ResultCodes::HUNG, NULL); |
| 68 base::CleanupProcesses(installer_util::kNaClExe, 15000, | 68 base::CleanupProcesses(installer::kNaClExe, 15000, |
| 69 ResultCodes::HUNG, NULL); | 69 ResultCodes::HUNG, NULL); |
| 70 } | 70 } |
| 71 | 71 |
| 72 // Attempts to close the Chrome Frame helper process by sending WM_CLOSE | 72 // Attempts to close the Chrome Frame helper process by sending WM_CLOSE |
| 73 // messages to its window, or just killing it if that doesn't work. | 73 // messages to its window, or just killing it if that doesn't work. |
| 74 void CloseChromeFrameHelperProcess() { | 74 void CloseChromeFrameHelperProcess() { |
| 75 HWND window = FindWindow(installer_util::kChromeFrameHelperWndClass, NULL); | 75 HWND window = FindWindow(installer::kChromeFrameHelperWndClass, NULL); |
| 76 if (!::IsWindow(window)) | 76 if (!::IsWindow(window)) |
| 77 return; | 77 return; |
| 78 | 78 |
| 79 const DWORD kWaitMs = 3000; | 79 const DWORD kWaitMs = 3000; |
| 80 | 80 |
| 81 DWORD pid = 0; | 81 DWORD pid = 0; |
| 82 ::GetWindowThreadProcessId(window, &pid); | 82 ::GetWindowThreadProcessId(window, &pid); |
| 83 DCHECK_NE(pid, 0U); | 83 DCHECK_NE(pid, 0U); |
| 84 ScopedHandle process(::OpenProcess(SYNCHRONIZE, FALSE, pid)); | 84 ScopedHandle process(::OpenProcess(SYNCHRONIZE, FALSE, pid)); |
| 85 PLOG_IF(INFO, !process) << "Failed to open process: " << pid; | 85 PLOG_IF(INFO, !process) << "Failed to open process: " << pid; |
| 86 | 86 |
| 87 bool kill = true; | 87 bool kill = true; |
| 88 if (SendMessageTimeout(window, WM_CLOSE, 0, 0, SMTO_BLOCK, kWaitMs, NULL) && | 88 if (SendMessageTimeout(window, WM_CLOSE, 0, 0, SMTO_BLOCK, kWaitMs, NULL) && |
| 89 process) { | 89 process) { |
| 90 VLOG(1) << "Waiting for " << installer_util::kChromeFrameHelperExe; | 90 VLOG(1) << "Waiting for " << installer::kChromeFrameHelperExe; |
| 91 DWORD wait = ::WaitForSingleObject(process, kWaitMs); | 91 DWORD wait = ::WaitForSingleObject(process, kWaitMs); |
| 92 if (wait != WAIT_OBJECT_0) { | 92 if (wait != WAIT_OBJECT_0) { |
| 93 LOG(WARNING) << "Wait for " << installer_util::kChromeFrameHelperExe | 93 LOG(WARNING) << "Wait for " << installer::kChromeFrameHelperExe |
| 94 << " to exit failed or timed out."; | 94 << " to exit failed or timed out."; |
| 95 } else { | 95 } else { |
| 96 kill = false; | 96 kill = false; |
| 97 VLOG(1) << installer_util::kChromeFrameHelperExe << " exited normally."; | 97 VLOG(1) << installer::kChromeFrameHelperExe << " exited normally."; |
| 98 } | 98 } |
| 99 } | 99 } |
| 100 | 100 |
| 101 if (kill) { | 101 if (kill) { |
| 102 VLOG(1) << installer_util::kChromeFrameHelperExe << " hung. Killing."; | 102 VLOG(1) << installer::kChromeFrameHelperExe << " hung. Killing."; |
| 103 base::CleanupProcesses(installer_util::kChromeFrameHelperExe, 0, | 103 base::CleanupProcesses(installer::kChromeFrameHelperExe, 0, |
| 104 ResultCodes::HUNG, NULL); | 104 ResultCodes::HUNG, NULL); |
| 105 } | 105 } |
| 106 } | 106 } |
| 107 | 107 |
| 108 // This method tries to figure out if current user has registered Chrome. | 108 // This method tries to figure out if current user has registered Chrome. |
| 109 // It returns true iff: | 109 // It returns true iff: |
| 110 // - Software\Clients\StartMenuInternet\Chromium\"" key has a valid value. | 110 // - Software\Clients\StartMenuInternet\Chromium\"" key has a valid value. |
| 111 // - The value is same as chrome.exe path for the current installation. | 111 // - The value is same as chrome.exe path for the current installation. |
| 112 bool CurrentUserHasDefaultBrowser(const Product& product) { | 112 bool CurrentUserHasDefaultBrowser(const Product& product) { |
| 113 std::wstring reg_key(ShellUtil::kRegStartMenuInternet); | 113 std::wstring reg_key(ShellUtil::kRegStartMenuInternet); |
| 114 reg_key.append(L"\\" + product.distribution()->GetApplicationName() + | 114 reg_key.append(L"\\" + product.distribution()->GetApplicationName() + |
| 115 ShellUtil::kRegShellOpen); | 115 ShellUtil::kRegShellOpen); |
| 116 RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ); | 116 RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ); |
| 117 std::wstring reg_exe; | 117 std::wstring reg_exe; |
| 118 if (key.ReadValue(L"", ®_exe) && reg_exe.length() > 2) { | 118 if (key.ReadValue(L"", ®_exe) && reg_exe.length() > 2) { |
| 119 FilePath chrome_exe(product.package().path() | 119 FilePath chrome_exe(product.package().path() |
| 120 .Append(installer_util::kChromeExe)); | 120 .Append(installer::kChromeExe)); |
| 121 // The path in the registry will always have quotes. | 121 // The path in the registry will always have quotes. |
| 122 reg_exe = reg_exe.substr(1, reg_exe.length() - 2); | 122 reg_exe = reg_exe.substr(1, reg_exe.length() - 2); |
| 123 if (FilePath::CompareEqualIgnoreCase(reg_exe, chrome_exe.value())) | 123 if (FilePath::CompareEqualIgnoreCase(reg_exe, chrome_exe.value())) |
| 124 return true; | 124 return true; |
| 125 } | 125 } |
| 126 | 126 |
| 127 return false; | 127 return false; |
| 128 } | 128 } |
| 129 | 129 |
| 130 // This method deletes Chrome shortcut folder from Windows Start menu. It | 130 // This method deletes Chrome shortcut folder from Windows Start menu. It |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 } | 334 } |
| 335 return result; | 335 return result; |
| 336 } | 336 } |
| 337 | 337 |
| 338 // This method checks if Chrome is currently running or if the user has | 338 // This method checks if Chrome is currently running or if the user has |
| 339 // cancelled the uninstall operation by clicking Cancel on the confirmation | 339 // cancelled the uninstall operation by clicking Cancel on the confirmation |
| 340 // box that Chrome pops up. | 340 // box that Chrome pops up. |
| 341 InstallStatus IsChromeActiveOrUserCancelled(const Product& product) { | 341 InstallStatus IsChromeActiveOrUserCancelled(const Product& product) { |
| 342 int32 exit_code = ResultCodes::NORMAL_EXIT; | 342 int32 exit_code = ResultCodes::NORMAL_EXIT; |
| 343 CommandLine options(CommandLine::NO_PROGRAM); | 343 CommandLine options(CommandLine::NO_PROGRAM); |
| 344 options.AppendSwitch(installer_util::switches::kUninstall); | 344 options.AppendSwitch(installer::switches::kUninstall); |
| 345 | 345 |
| 346 // Here we want to save user from frustration (in case of Chrome crashes) | 346 // Here we want to save user from frustration (in case of Chrome crashes) |
| 347 // and continue with the uninstallation as long as chrome.exe process exit | 347 // and continue with the uninstallation as long as chrome.exe process exit |
| 348 // code is NOT one of the following: | 348 // code is NOT one of the following: |
| 349 // - UNINSTALL_CHROME_ALIVE - chrome.exe is currently running | 349 // - UNINSTALL_CHROME_ALIVE - chrome.exe is currently running |
| 350 // - UNINSTALL_USER_CANCEL - User cancelled uninstallation | 350 // - UNINSTALL_USER_CANCEL - User cancelled uninstallation |
| 351 // - HUNG - chrome.exe was killed by HuntForZombieProcesses() (until we can | 351 // - HUNG - chrome.exe was killed by HuntForZombieProcesses() (until we can |
| 352 // give this method some brains and not kill chrome.exe launched | 352 // give this method some brains and not kill chrome.exe launched |
| 353 // by us, we will not uninstall if we get this return code). | 353 // by us, we will not uninstall if we get this return code). |
| 354 VLOG(1) << "Launching Chrome to do uninstall tasks."; | 354 VLOG(1) << "Launching Chrome to do uninstall tasks."; |
| 355 if (product.LaunchChromeAndWait(options, &exit_code)) { | 355 if (product.LaunchChromeAndWait(options, &exit_code)) { |
| 356 VLOG(1) << "chrome.exe launched for uninstall confirmation returned: " | 356 VLOG(1) << "chrome.exe launched for uninstall confirmation returned: " |
| 357 << exit_code; | 357 << exit_code; |
| 358 if ((exit_code == ResultCodes::UNINSTALL_CHROME_ALIVE) || | 358 if ((exit_code == ResultCodes::UNINSTALL_CHROME_ALIVE) || |
| 359 (exit_code == ResultCodes::UNINSTALL_USER_CANCEL) || | 359 (exit_code == ResultCodes::UNINSTALL_USER_CANCEL) || |
| 360 (exit_code == ResultCodes::HUNG)) | 360 (exit_code == ResultCodes::HUNG)) |
| 361 return installer_util::UNINSTALL_CANCELLED; | 361 return installer::UNINSTALL_CANCELLED; |
| 362 | 362 |
| 363 if (exit_code == ResultCodes::UNINSTALL_DELETE_PROFILE) | 363 if (exit_code == ResultCodes::UNINSTALL_DELETE_PROFILE) |
| 364 return installer_util::UNINSTALL_DELETE_PROFILE; | 364 return installer::UNINSTALL_DELETE_PROFILE; |
| 365 } else { | 365 } else { |
| 366 PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation."; | 366 PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation."; |
| 367 } | 367 } |
| 368 | 368 |
| 369 return installer_util::UNINSTALL_CONFIRMED; | 369 return installer::UNINSTALL_CONFIRMED; |
| 370 } | 370 } |
| 371 | 371 |
| 372 bool ShouldDeleteProfile(const CommandLine& cmd_line, InstallStatus status, | 372 bool ShouldDeleteProfile(const CommandLine& cmd_line, InstallStatus status, |
| 373 const Product& product) { | 373 const Product& product) { |
| 374 bool should_delete = false; | 374 bool should_delete = false; |
| 375 | 375 |
| 376 // Chrome Frame uninstallations always want to delete the profile (we have no | 376 // Chrome Frame uninstallations always want to delete the profile (we have no |
| 377 // UI to prompt otherwise and the profile stores no useful data anyway) | 377 // UI to prompt otherwise and the profile stores no useful data anyway) |
| 378 // unless they are managed by MSI. MSI uninstalls will explicitly include | 378 // unless they are managed by MSI. MSI uninstalls will explicitly include |
| 379 // the --delete-profile flag to distinguish them from MSI upgrades. | 379 // the --delete-profile flag to distinguish them from MSI upgrades. |
| 380 if (product.distribution()->GetType() != | 380 if (product.distribution()->GetType() != |
| 381 BrowserDistribution::CHROME_BROWSER && !product.IsMsi()) { | 381 BrowserDistribution::CHROME_BROWSER && !product.IsMsi()) { |
| 382 should_delete = true; | 382 should_delete = true; |
| 383 } else { | 383 } else { |
| 384 should_delete = | 384 should_delete = |
| 385 status == installer_util::UNINSTALL_DELETE_PROFILE || | 385 status == installer::UNINSTALL_DELETE_PROFILE || |
| 386 cmd_line.HasSwitch(installer_util::switches::kDeleteProfile); | 386 cmd_line.HasSwitch(installer::switches::kDeleteProfile); |
| 387 } | 387 } |
| 388 | 388 |
| 389 return should_delete; | 389 return should_delete; |
| 390 } | 390 } |
| 391 | 391 |
| 392 bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root, | 392 bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root, |
| 393 const std::wstring& browser_entry_suffix, | 393 const std::wstring& browser_entry_suffix, |
| 394 InstallStatus& exit_code) { | 394 InstallStatus& exit_code) { |
| 395 if (!dist->CanSetAsDefault()) { | 395 if (!dist->CanSetAsDefault()) { |
| 396 // We should have never set those keys. | 396 // We should have never set those keys. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 411 // Delete Software\Clients\StartMenuInternet\Chromium | 411 // Delete Software\Clients\StartMenuInternet\Chromium |
| 412 std::wstring set_access_key(ShellUtil::kRegStartMenuInternet); | 412 std::wstring set_access_key(ShellUtil::kRegStartMenuInternet); |
| 413 file_util::AppendToPath(&set_access_key, dist->GetApplicationName()); | 413 file_util::AppendToPath(&set_access_key, dist->GetApplicationName()); |
| 414 set_access_key.append(browser_entry_suffix); | 414 set_access_key.append(browser_entry_suffix); |
| 415 InstallUtil::DeleteRegistryKey(key, set_access_key); | 415 InstallUtil::DeleteRegistryKey(key, set_access_key); |
| 416 | 416 |
| 417 // We have renamed the StartMenuInternet\chrome.exe to | 417 // We have renamed the StartMenuInternet\chrome.exe to |
| 418 // StartMenuInternet\Chromium so for old users we still need to delete | 418 // StartMenuInternet\Chromium so for old users we still need to delete |
| 419 // the old key. | 419 // the old key. |
| 420 std::wstring old_set_access_key(ShellUtil::kRegStartMenuInternet); | 420 std::wstring old_set_access_key(ShellUtil::kRegStartMenuInternet); |
| 421 file_util::AppendToPath(&old_set_access_key, installer_util::kChromeExe); | 421 file_util::AppendToPath(&old_set_access_key, installer::kChromeExe); |
| 422 InstallUtil::DeleteRegistryKey(key, old_set_access_key); | 422 InstallUtil::DeleteRegistryKey(key, old_set_access_key); |
| 423 | 423 |
| 424 // Delete Software\RegisteredApplications\Chromium | 424 // Delete Software\RegisteredApplications\Chromium |
| 425 InstallUtil::DeleteRegistryValue(root, ShellUtil::kRegRegisteredApplications, | 425 InstallUtil::DeleteRegistryValue(root, ShellUtil::kRegRegisteredApplications, |
| 426 dist->GetApplicationName() + browser_entry_suffix); | 426 dist->GetApplicationName() + browser_entry_suffix); |
| 427 | 427 |
| 428 // Delete Software\Classes\Applications\chrome.exe | 428 // Delete Software\Classes\Applications\chrome.exe |
| 429 std::wstring app_key(ShellUtil::kRegClasses); | 429 std::wstring app_key(ShellUtil::kRegClasses); |
| 430 file_util::AppendToPath(&app_key, L"Applications"); | 430 file_util::AppendToPath(&app_key, L"Applications"); |
| 431 file_util::AppendToPath(&app_key, installer_util::kChromeExe); | 431 file_util::AppendToPath(&app_key, installer::kChromeExe); |
| 432 InstallUtil::DeleteRegistryKey(key, app_key); | 432 InstallUtil::DeleteRegistryKey(key, app_key); |
| 433 | 433 |
| 434 // Delete the App Paths key that lets explorer find Chrome. | 434 // Delete the App Paths key that lets explorer find Chrome. |
| 435 std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey); | 435 std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey); |
| 436 file_util::AppendToPath(&app_path_key, installer_util::kChromeExe); | 436 file_util::AppendToPath(&app_path_key, installer::kChromeExe); |
| 437 InstallUtil::DeleteRegistryKey(key, app_path_key); | 437 InstallUtil::DeleteRegistryKey(key, app_path_key); |
| 438 | 438 |
| 439 // Cleanup OpenWithList | 439 // Cleanup OpenWithList |
| 440 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { | 440 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { |
| 441 std::wstring open_with_key(ShellUtil::kRegClasses); | 441 std::wstring open_with_key(ShellUtil::kRegClasses); |
| 442 file_util::AppendToPath(&open_with_key, ShellUtil::kFileAssociations[i]); | 442 file_util::AppendToPath(&open_with_key, ShellUtil::kFileAssociations[i]); |
| 443 file_util::AppendToPath(&open_with_key, L"OpenWithList"); | 443 file_util::AppendToPath(&open_with_key, L"OpenWithList"); |
| 444 file_util::AppendToPath(&open_with_key, installer_util::kChromeExe); | 444 file_util::AppendToPath(&open_with_key, installer::kChromeExe); |
| 445 InstallUtil::DeleteRegistryKey(key, open_with_key); | 445 InstallUtil::DeleteRegistryKey(key, open_with_key); |
| 446 } | 446 } |
| 447 | 447 |
| 448 key.Close(); | 448 key.Close(); |
| 449 exit_code = installer_util::UNINSTALL_SUCCESSFUL; | 449 exit_code = installer::UNINSTALL_SUCCESSFUL; |
| 450 return true; | 450 return true; |
| 451 } | 451 } |
| 452 | 452 |
| 453 void RemoveLegacyRegistryKeys(BrowserDistribution* dist) { | 453 void RemoveLegacyRegistryKeys(BrowserDistribution* dist) { |
| 454 // We used to register Chrome to handle crx files, but this turned out | 454 // We used to register Chrome to handle crx files, but this turned out |
| 455 // to be not worth the hassle. Remove these old registry entries if | 455 // to be not worth the hassle. Remove these old registry entries if |
| 456 // they exist. See: http://codereview.chromium.org/210007 | 456 // they exist. See: http://codereview.chromium.org/210007 |
| 457 | 457 |
| 458 #if defined(GOOGLE_CHROME_BUILD) | 458 #if defined(GOOGLE_CHROME_BUILD) |
| 459 const wchar_t kChromeExtProgId[] = L"ChromeExt"; | 459 const wchar_t kChromeExtProgId[] = L"ChromeExt"; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 482 ext_association.append(chrome::kExtensionFileExtension); | 482 ext_association.append(chrome::kExtensionFileExtension); |
| 483 InstallUtil::DeleteRegistryKey(key, ext_association); | 483 InstallUtil::DeleteRegistryKey(key, ext_association); |
| 484 } | 484 } |
| 485 } | 485 } |
| 486 | 486 |
| 487 InstallStatus UninstallChrome(const FilePath& setup_path, | 487 InstallStatus UninstallChrome(const FilePath& setup_path, |
| 488 const Product& product, | 488 const Product& product, |
| 489 bool remove_all, | 489 bool remove_all, |
| 490 bool force_uninstall, | 490 bool force_uninstall, |
| 491 const CommandLine& cmd_line) { | 491 const CommandLine& cmd_line) { |
| 492 InstallStatus status = installer_util::UNINSTALL_CONFIRMED; | 492 InstallStatus status = installer::UNINSTALL_CONFIRMED; |
| 493 std::wstring suffix; | 493 std::wstring suffix; |
| 494 if (!ShellUtil::GetUserSpecificDefaultBrowserSuffix(product.distribution(), | 494 if (!ShellUtil::GetUserSpecificDefaultBrowserSuffix(product.distribution(), |
| 495 &suffix)) | 495 &suffix)) |
| 496 suffix = L""; | 496 suffix = L""; |
| 497 | 497 |
| 498 BrowserDistribution* browser_dist = product.distribution(); | 498 BrowserDistribution* browser_dist = product.distribution(); |
| 499 bool is_chrome = (browser_dist->GetType() == | 499 bool is_chrome = (browser_dist->GetType() == |
| 500 BrowserDistribution::CHROME_BROWSER); | 500 BrowserDistribution::CHROME_BROWSER); |
| 501 | 501 |
| 502 VLOG(1) << "UninstallChrome: " << browser_dist->GetApplicationName(); | 502 VLOG(1) << "UninstallChrome: " << browser_dist->GetApplicationName(); |
| 503 | 503 |
| 504 if (force_uninstall) { | 504 if (force_uninstall) { |
| 505 // Since --force-uninstall command line option is used, we are going to | 505 // Since --force-uninstall command line option is used, we are going to |
| 506 // do silent uninstall. Try to close all running Chrome instances. | 506 // do silent uninstall. Try to close all running Chrome instances. |
| 507 // NOTE: We don't do this for Chrome Frame or CEEE. | 507 // NOTE: We don't do this for Chrome Frame or CEEE. |
| 508 if (is_chrome) | 508 if (is_chrome) |
| 509 CloseAllChromeProcesses(); | 509 CloseAllChromeProcesses(); |
| 510 } else if (is_chrome) { | 510 } else if (is_chrome) { |
| 511 // no --force-uninstall so lets show some UI dialog boxes. | 511 // no --force-uninstall so lets show some UI dialog boxes. |
| 512 status = IsChromeActiveOrUserCancelled(product); | 512 status = IsChromeActiveOrUserCancelled(product); |
| 513 if (status != installer_util::UNINSTALL_CONFIRMED && | 513 if (status != installer::UNINSTALL_CONFIRMED && |
| 514 status != installer_util::UNINSTALL_DELETE_PROFILE) | 514 status != installer::UNINSTALL_DELETE_PROFILE) |
| 515 return status; | 515 return status; |
| 516 | 516 |
| 517 // Check if we need admin rights to cleanup HKLM. If we do, try to launch | 517 // Check if we need admin rights to cleanup HKLM. If we do, try to launch |
| 518 // another uninstaller (silent) in elevated mode to do HKLM cleanup. | 518 // another uninstaller (silent) in elevated mode to do HKLM cleanup. |
| 519 // And continue uninstalling in the current process also to do HKCU cleanup. | 519 // And continue uninstalling in the current process also to do HKCU cleanup. |
| 520 if (remove_all && | 520 if (remove_all && |
| 521 (!suffix.empty() || CurrentUserHasDefaultBrowser(product)) && | 521 (!suffix.empty() || CurrentUserHasDefaultBrowser(product)) && |
| 522 !::IsUserAnAdmin() && | 522 !::IsUserAnAdmin() && |
| 523 base::win::GetVersion() >= base::win::VERSION_VISTA && | 523 base::win::GetVersion() >= base::win::VERSION_VISTA && |
| 524 !cmd_line.HasSwitch(installer_util::switches::kRunAsAdmin)) { | 524 !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { |
| 525 CommandLine new_cmd(CommandLine::NO_PROGRAM); | 525 CommandLine new_cmd(CommandLine::NO_PROGRAM); |
| 526 new_cmd.AppendArguments(cmd_line, true); | 526 new_cmd.AppendArguments(cmd_line, true); |
| 527 // Append --run-as-admin flag to let the new instance of setup.exe know | 527 // Append --run-as-admin flag to let the new instance of setup.exe know |
| 528 // that we already tried to launch ourselves as admin. | 528 // that we already tried to launch ourselves as admin. |
| 529 new_cmd.AppendSwitch(installer_util::switches::kRunAsAdmin); | 529 new_cmd.AppendSwitch(installer::switches::kRunAsAdmin); |
| 530 // Append --remove-chrome-registration to remove registry keys only. | 530 // Append --remove-chrome-registration to remove registry keys only. |
| 531 new_cmd.AppendSwitch(installer_util::switches::kRemoveChromeRegistration); | 531 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration); |
| 532 if (!suffix.empty()) { | 532 if (!suffix.empty()) { |
| 533 new_cmd.AppendSwitchNative( | 533 new_cmd.AppendSwitchNative( |
| 534 installer_util::switches::kRegisterChromeBrowserSuffix, suffix); | 534 installer::switches::kRegisterChromeBrowserSuffix, suffix); |
| 535 } | 535 } |
| 536 DWORD exit_code = installer_util::UNKNOWN_STATUS; | 536 DWORD exit_code = installer::UNKNOWN_STATUS; |
| 537 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); | 537 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); |
| 538 } | 538 } |
| 539 } | 539 } |
| 540 | 540 |
| 541 // Get the version of installed Chrome (if any) | 541 // Get the version of installed Chrome (if any) |
| 542 scoped_ptr<installer::Version> | 542 scoped_ptr<installer::Version> |
| 543 installed_version(InstallUtil::GetChromeVersion(browser_dist, | 543 installed_version(InstallUtil::GetChromeVersion(browser_dist, |
| 544 product.system_level())); | 544 product.system_level())); |
| 545 | 545 |
| 546 // Chrome is not in use so lets uninstall Chrome by deleting various files | 546 // Chrome is not in use so lets uninstall Chrome by deleting various files |
| (...skipping 16 matching lines...) Expand all Loading... |
| 563 InstallUtil::DeleteRegistryKey(key, browser_dist->GetUninstallRegPath()); | 563 InstallUtil::DeleteRegistryKey(key, browser_dist->GetUninstallRegPath()); |
| 564 InstallUtil::DeleteRegistryKey(key, browser_dist->GetVersionKey()); | 564 InstallUtil::DeleteRegistryKey(key, browser_dist->GetVersionKey()); |
| 565 | 565 |
| 566 // Also try to delete the MSI value in the ClientState key (it might not be | 566 // Also try to delete the MSI value in the ClientState key (it might not be |
| 567 // there). This is due to a Google Update behaviour where an uninstall and a | 567 // there). This is due to a Google Update behaviour where an uninstall and a |
| 568 // rapid reinstall might result in stale values from the old ClientState key | 568 // rapid reinstall might result in stale values from the old ClientState key |
| 569 // being picked up on reinstall. | 569 // being picked up on reinstall. |
| 570 product.SetMsiMarker(false); | 570 product.SetMsiMarker(false); |
| 571 | 571 |
| 572 // Remove all Chrome registration keys. | 572 // Remove all Chrome registration keys. |
| 573 InstallStatus ret = installer_util::UNKNOWN_STATUS; | 573 InstallStatus ret = installer::UNKNOWN_STATUS; |
| 574 DeleteChromeRegistrationKeys(product.distribution(), reg_root, suffix, ret); | 574 DeleteChromeRegistrationKeys(product.distribution(), reg_root, suffix, ret); |
| 575 | 575 |
| 576 // For user level install also we end up creating some keys in HKLM if user | 576 // For user level install also we end up creating some keys in HKLM if user |
| 577 // sets Chrome as default browser. So delete those as well (needs admin). | 577 // sets Chrome as default browser. So delete those as well (needs admin). |
| 578 if (remove_all && !product.system_level() && | 578 if (remove_all && !product.system_level() && |
| 579 (!suffix.empty() || CurrentUserHasDefaultBrowser(product))) { | 579 (!suffix.empty() || CurrentUserHasDefaultBrowser(product))) { |
| 580 DeleteChromeRegistrationKeys(product.distribution(), HKEY_LOCAL_MACHINE, | 580 DeleteChromeRegistrationKeys(product.distribution(), HKEY_LOCAL_MACHINE, |
| 581 suffix, ret); | 581 suffix, ret); |
| 582 } | 582 } |
| 583 | 583 |
| 584 // Delete shared registry keys as well (these require admin rights) if | 584 // Delete shared registry keys as well (these require admin rights) if |
| 585 // remove_all option is specified. | 585 // remove_all option is specified. |
| 586 if (remove_all) { | 586 if (remove_all) { |
| 587 if (!InstallUtil::IsChromeSxSProcess() && is_chrome) { | 587 if (!InstallUtil::IsChromeSxSProcess() && is_chrome) { |
| 588 // Delete media player registry key that exists only in HKLM. | 588 // Delete media player registry key that exists only in HKLM. |
| 589 // We don't delete this key in SxS uninstall or Chrome Frame uninstall | 589 // We don't delete this key in SxS uninstall or Chrome Frame uninstall |
| 590 // as we never set the key for those products. | 590 // as we never set the key for those products. |
| 591 RegKey hklm_key(HKEY_LOCAL_MACHINE, L"", KEY_ALL_ACCESS); | 591 RegKey hklm_key(HKEY_LOCAL_MACHINE, L"", KEY_ALL_ACCESS); |
| 592 std::wstring reg_path(installer::kMediaPlayerRegPath); | 592 std::wstring reg_path(installer::kMediaPlayerRegPath); |
| 593 file_util::AppendToPath(®_path, installer_util::kChromeExe); | 593 file_util::AppendToPath(®_path, installer::kChromeExe); |
| 594 InstallUtil::DeleteRegistryKey(hklm_key, reg_path); | 594 InstallUtil::DeleteRegistryKey(hklm_key, reg_path); |
| 595 hklm_key.Close(); | 595 hklm_key.Close(); |
| 596 } | 596 } |
| 597 | 597 |
| 598 // Unregister any dll servers that we may have registered for Chrome Frame | 598 // Unregister any dll servers that we may have registered for Chrome Frame |
| 599 // and CEEE builds only. | 599 // and CEEE builds only. |
| 600 // TODO(tommi): We should only do this when the folder itself is | 600 // TODO(tommi): We should only do this when the folder itself is |
| 601 // being removed and we know that the DLLs were previously registered. | 601 // being removed and we know that the DLLs were previously registered. |
| 602 // Simplest would be to always register them. | 602 // Simplest would be to always register them. |
| 603 if (installed_version.get() && !is_chrome) { | 603 if (installed_version.get() && !is_chrome) { |
| 604 RegisterComDllList(product.package().path().Append( | 604 RegisterComDllList(product.package().path().Append( |
| 605 installed_version->GetString()), | 605 installed_version->GetString()), |
| 606 product.system_level(), false, false); | 606 product.system_level(), false, false); |
| 607 } | 607 } |
| 608 } | 608 } |
| 609 | 609 |
| 610 // Close any Chrome Frame helper processes that may be running. | 610 // Close any Chrome Frame helper processes that may be running. |
| 611 if (product.distribution()->GetType() == BrowserDistribution::CHROME_FRAME) { | 611 if (product.distribution()->GetType() == BrowserDistribution::CHROME_FRAME) { |
| 612 VLOG(1) << "Closing the Chrome Frame helper process"; | 612 VLOG(1) << "Closing the Chrome Frame helper process"; |
| 613 CloseChromeFrameHelperProcess(); | 613 CloseChromeFrameHelperProcess(); |
| 614 } | 614 } |
| 615 | 615 |
| 616 if (!installed_version.get()) | 616 if (!installed_version.get()) |
| 617 return installer_util::UNINSTALL_SUCCESSFUL; | 617 return installer::UNINSTALL_SUCCESSFUL; |
| 618 | 618 |
| 619 // Finally delete all the files from Chrome folder after moving setup.exe | 619 // Finally delete all the files from Chrome folder after moving setup.exe |
| 620 // and the user's Local State to a temp location. | 620 // and the user's Local State to a temp location. |
| 621 bool delete_profile = ShouldDeleteProfile(cmd_line, status, product); | 621 bool delete_profile = ShouldDeleteProfile(cmd_line, status, product); |
| 622 ret = installer_util::UNINSTALL_SUCCESSFUL; | 622 ret = installer::UNINSTALL_SUCCESSFUL; |
| 623 | 623 |
| 624 // In order to be able to remove the folder in which we're running, we | 624 // In order to be able to remove the folder in which we're running, we |
| 625 // need to move setup.exe out of the install folder. | 625 // need to move setup.exe out of the install folder. |
| 626 // TODO(tommi): What if the temp folder is on a different volume? | 626 // TODO(tommi): What if the temp folder is on a different volume? |
| 627 MoveSetupOutOfInstallFolder(product.package(), setup_path, | 627 MoveSetupOutOfInstallFolder(product.package(), setup_path, |
| 628 *installed_version); | 628 *installed_version); |
| 629 | 629 |
| 630 FilePath backup_state_file(BackupLocalStateFile( | 630 FilePath backup_state_file(BackupLocalStateFile( |
| 631 GetLocalStateFolder(product))); | 631 GetLocalStateFolder(product))); |
| 632 | 632 |
| 633 // TODO(tommi): We should only do this when the last distribution is being | 633 // TODO(tommi): We should only do this when the last distribution is being |
| 634 // uninstalled. | 634 // uninstalled. |
| 635 DeleteResult delete_result = DeleteFilesAndFolders(product.package(), | 635 DeleteResult delete_result = DeleteFilesAndFolders(product.package(), |
| 636 *installed_version); | 636 *installed_version); |
| 637 | 637 |
| 638 if (delete_profile) | 638 if (delete_profile) |
| 639 DeleteLocalState(product); | 639 DeleteLocalState(product); |
| 640 | 640 |
| 641 if (delete_result == DELETE_FAILED) { | 641 if (delete_result == DELETE_FAILED) { |
| 642 ret = installer_util::UNINSTALL_FAILED; | 642 ret = installer::UNINSTALL_FAILED; |
| 643 } else if (delete_result == DELETE_REQUIRES_REBOOT) { | 643 } else if (delete_result == DELETE_REQUIRES_REBOOT) { |
| 644 ret = installer_util::UNINSTALL_REQUIRES_REBOOT; | 644 ret = installer::UNINSTALL_REQUIRES_REBOOT; |
| 645 } | 645 } |
| 646 | 646 |
| 647 if (!force_uninstall) { | 647 if (!force_uninstall) { |
| 648 VLOG(1) << "Uninstallation complete. Launching Uninstall survey."; | 648 VLOG(1) << "Uninstallation complete. Launching Uninstall survey."; |
| 649 browser_dist->DoPostUninstallOperations(*installed_version, | 649 browser_dist->DoPostUninstallOperations(*installed_version, |
| 650 backup_state_file, distribution_data); | 650 backup_state_file, distribution_data); |
| 651 } | 651 } |
| 652 | 652 |
| 653 // Try and delete the preserved local state once the post-install | 653 // Try and delete the preserved local state once the post-install |
| 654 // operations are complete. | 654 // operations are complete. |
| 655 if (!backup_state_file.empty()) | 655 if (!backup_state_file.empty()) |
| 656 file_util::Delete(backup_state_file, false); | 656 file_util::Delete(backup_state_file, false); |
| 657 | 657 |
| 658 return ret; | 658 return ret; |
| 659 } | 659 } |
| 660 | 660 |
| 661 } // namespace installer | 661 } // namespace installer |
| 662 | 662 |
| OLD | NEW |