| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/installer/util/helper.h" | 5 #include "chrome/installer/util/helper.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/logging.h" |
| 8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
| 9 #include "base/logging.h" | |
| 10 #include "base/path_service.h" | 9 #include "base/path_service.h" |
| 11 #include "base/win/registry.h" | |
| 12 #include "chrome/installer/util/browser_distribution.h" | 10 #include "chrome/installer/util/browser_distribution.h" |
| 11 #include "chrome/installer/util/installation_state.h" |
| 13 #include "chrome/installer/util/install_util.h" | 12 #include "chrome/installer/util/install_util.h" |
| 14 #include "chrome/installer/util/master_preferences.h" | 13 #include "chrome/installer/util/util_constants.h" |
| 15 #include "chrome/installer/util/package_properties.h" | |
| 16 | |
| 17 using base::win::RegKey; | |
| 18 | 14 |
| 19 namespace { | 15 namespace { |
| 20 | 16 |
| 21 FilePath GetChromeInstallBasePath(bool system, | 17 FilePath GetChromeInstallBasePath(bool system, |
| 22 BrowserDistribution* distribution, | 18 BrowserDistribution* distribution, |
| 23 const wchar_t* sub_path) { | 19 const wchar_t* sub_path) { |
| 24 FilePath install_path; | 20 FilePath install_path; |
| 25 if (system) { | 21 if (system) { |
| 26 PathService::Get(base::DIR_PROGRAM_FILES, &install_path); | 22 PathService::Get(base::DIR_PROGRAM_FILES, &install_path); |
| 27 } else { | 23 } else { |
| 28 PathService::Get(base::DIR_LOCAL_APP_DATA, &install_path); | 24 PathService::Get(base::DIR_LOCAL_APP_DATA, &install_path); |
| 29 } | 25 } |
| 30 | 26 |
| 31 if (!install_path.empty()) { | 27 if (!install_path.empty()) { |
| 32 install_path = install_path.Append(distribution->GetInstallSubDir()); | 28 install_path = install_path.Append(distribution->GetInstallSubDir()); |
| 33 install_path = install_path.Append(sub_path); | 29 install_path = install_path.Append(sub_path); |
| 34 } | 30 } |
| 35 | 31 |
| 36 return install_path; | 32 return install_path; |
| 37 } | 33 } |
| 38 | 34 |
| 39 } // namespace | 35 } // namespace |
| 40 | 36 |
| 41 namespace installer { | 37 namespace installer { |
| 42 | 38 |
| 43 bool IsInstalledAsMulti(bool system_install, BrowserDistribution* dist) { | |
| 44 bool installed_as_multi = false; | |
| 45 CommandLine cmd(CommandLine::NO_PROGRAM); | |
| 46 if (GetUninstallSwitches(system_install, dist, &cmd)) | |
| 47 installed_as_multi = cmd.HasSwitch(installer::switches::kMultiInstall); | |
| 48 return installed_as_multi; | |
| 49 } | |
| 50 | |
| 51 bool GetUninstallSwitches(bool system_install, BrowserDistribution* dist, | |
| 52 CommandLine* cmd_line_switches) { | |
| 53 scoped_ptr<Version> installed(InstallUtil::GetChromeVersion(dist, | |
| 54 system_install)); | |
| 55 if (installed.get()) { | |
| 56 HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | |
| 57 RegKey key(root, dist->GetStateKey().c_str(), KEY_READ); | |
| 58 if (key.Valid()) { | |
| 59 std::wstring args; | |
| 60 key.ReadValue(installer::kUninstallArgumentsField, &args); | |
| 61 if (!args.empty()) { | |
| 62 args.insert(0, L"foo.exe "); | |
| 63 *cmd_line_switches = CommandLine::FromString(args); | |
| 64 } else { | |
| 65 LOG(ERROR) << "No uninstallation arguments for " | |
| 66 << dist->GetApplicationName(); | |
| 67 installed.reset(); | |
| 68 } | |
| 69 } else { | |
| 70 LOG(ERROR) << "Product looks to be installed but we can't access the " | |
| 71 "state key: " << dist->GetApplicationName(); | |
| 72 installed.reset(); | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 return installed.get() != NULL; | |
| 77 } | |
| 78 | |
| 79 FilePath GetChromeInstallPath(bool system_install, BrowserDistribution* dist) { | 39 FilePath GetChromeInstallPath(bool system_install, BrowserDistribution* dist) { |
| 80 return GetChromeInstallBasePath(system_install, dist, | 40 return GetChromeInstallBasePath(system_install, dist, kInstallBinaryDir); |
| 81 installer::kInstallBinaryDir); | |
| 82 } | 41 } |
| 83 | 42 |
| 84 FilePath GetChromeUserDataPath(BrowserDistribution* dist) { | 43 FilePath GetChromeUserDataPath(BrowserDistribution* dist) { |
| 85 return GetChromeInstallBasePath(false, dist, kInstallUserDataDir); | 44 return GetChromeInstallBasePath(false, dist, kInstallUserDataDir); |
| 86 } | 45 } |
| 87 | 46 |
| 88 FilePath GetChromeFrameInstallPath(bool multi_install, bool system_install, | 47 BrowserDistribution* GetBinariesDistribution(bool system_install) { |
| 89 BrowserDistribution* dist) { | 48 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| 90 DCHECK_EQ(BrowserDistribution::CHROME_FRAME, dist->GetType()); | 49 ProductState state; |
| 91 | 50 |
| 92 scoped_ptr<Version> installed_version( | 51 // If we're part of a multi-install, we need to poll using the multi-installer |
| 93 InstallUtil::GetChromeVersion(dist, system_install)); | 52 // package's app guid rather than the browser's or Chrome Frame's app guid. |
| 94 | 53 // If we can't read the app's state from the registry, assume it isn't |
| 95 if (!multi_install) { | 54 // multi-installed. |
| 96 // Check if Chrome Frame is installed as multi. If it is, return an empty | 55 if (state.Initialize(system_install, dist) && state.is_multi_install()) { |
| 97 // path and log an error. | 56 return BrowserDistribution::GetSpecificDistribution( |
| 98 if (installed_version.get() && IsInstalledAsMulti(system_install, dist)) { | 57 BrowserDistribution::CHROME_BINARIES); |
| 99 LOG(ERROR) << "Cannot install Chrome Frame in single mode as a multi mode" | 58 } else { |
| 100 " installation already exists."; | 59 return dist; |
| 101 return FilePath(); | |
| 102 } | |
| 103 VLOG(1) << "Chrome Frame will be installed as 'single'"; | |
| 104 return GetChromeInstallPath(system_install, dist); | |
| 105 } | 60 } |
| 106 | |
| 107 // TODO(tommi): If Chrome Frame is installed as single and the installed | |
| 108 // channel is older than the one we're installing, we should migrate | |
| 109 // CF to Chrome's install folder and change its channel. | |
| 110 | |
| 111 // Multi install. Check if Chrome Frame is already installed. | |
| 112 // If CF is installed as single (i.e. not multi), we will return an empty | |
| 113 // path (for now). Otherwise, if CF is not installed or if it is installed | |
| 114 // as multi, we will return Chrome's install folder. | |
| 115 if (installed_version.get() && !IsInstalledAsMulti(system_install, dist)) { | |
| 116 LOG(ERROR) << "Cannot install Chrome Frame in multi mode as a single mode" | |
| 117 " installation already exists."; | |
| 118 return FilePath(); | |
| 119 } | |
| 120 | |
| 121 // Return Chrome's installation folder. | |
| 122 VLOG(1) << "Chrome Frame will be installed as 'multi'"; | |
| 123 const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess(); | |
| 124 BrowserDistribution* chrome = | |
| 125 BrowserDistribution::GetSpecificDistribution( | |
| 126 BrowserDistribution::CHROME_BROWSER, prefs); | |
| 127 return GetChromeInstallPath(system_install, chrome); | |
| 128 } | 61 } |
| 129 | 62 |
| 130 std::wstring GetAppGuidForUpdates(bool system_install) { | 63 std::wstring GetAppGuidForUpdates(bool system_install) { |
| 131 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 64 return GetBinariesDistribution(system_install)->GetAppGuid(); |
| 132 | |
| 133 // If we're part of a multi-install, we need to poll using the multi-installer | |
| 134 // package's app guid rather than the browser's or Chrome Frame's app guid. | |
| 135 return IsInstalledAsMulti(system_install, dist) ? | |
| 136 ActivePackageProperties().GetAppGuid() : | |
| 137 dist->GetAppGuid(); | |
| 138 } | 65 } |
| 139 | 66 |
| 140 } // namespace installer. | 67 } // namespace installer. |
| OLD | NEW |