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

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

Issue 2589753002: Remove multi-install from chrome/installer/setup. (Closed)
Patch Set: sync to position 442053 Created 3 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
« no previous file with comments | « chrome/installer/setup/setup_util.h ('k') | chrome/installer/setup/setup_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 declares util functions for setup project. 5 // This file declares util functions for setup project.
6 6
7 #include "chrome/installer/setup/setup_util.h" 7 #include "chrome/installer/setup/setup_util.h"
8 8
9 #include <windows.h> 9 #include <windows.h>
10 #include <stddef.h> 10 #include <stddef.h>
(...skipping 24 matching lines...) Expand all
35 #include "base/win/windows_version.h" 35 #include "base/win/windows_version.h"
36 #include "chrome/installer/setup/installer_state.h" 36 #include "chrome/installer/setup/installer_state.h"
37 #include "chrome/installer/setup/setup_constants.h" 37 #include "chrome/installer/setup/setup_constants.h"
38 #include "chrome/installer/setup/user_hive_visitor.h" 38 #include "chrome/installer/setup/user_hive_visitor.h"
39 #include "chrome/installer/util/app_registration_data.h" 39 #include "chrome/installer/util/app_registration_data.h"
40 #include "chrome/installer/util/google_update_constants.h" 40 #include "chrome/installer/util/google_update_constants.h"
41 #include "chrome/installer/util/install_util.h" 41 #include "chrome/installer/util/install_util.h"
42 #include "chrome/installer/util/installation_state.h" 42 #include "chrome/installer/util/installation_state.h"
43 #include "chrome/installer/util/master_preferences.h" 43 #include "chrome/installer/util/master_preferences.h"
44 #include "chrome/installer/util/master_preferences_constants.h" 44 #include "chrome/installer/util/master_preferences_constants.h"
45 #include "chrome/installer/util/non_updating_app_registration_data.h"
46 #include "chrome/installer/util/updating_app_registration_data.h"
45 #include "chrome/installer/util/util_constants.h" 47 #include "chrome/installer/util/util_constants.h"
46 #include "courgette/courgette.h" 48 #include "courgette/courgette.h"
47 #include "courgette/third_party/bsdiff/bsdiff.h" 49 #include "courgette/third_party/bsdiff/bsdiff.h"
48 50
49 namespace installer { 51 namespace installer {
50 52
51 namespace { 53 namespace {
52 54
53 // Event log providers registry location. 55 // Event log providers registry location.
54 constexpr wchar_t kEventLogProvidersRegPath[] = 56 constexpr wchar_t kEventLogProvidersRegPath[] =
55 L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"; 57 L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\";
56 58
57 // TODO(grt): use install_static::InstallDetails::Get().install_full_name() when 59 // TODO(grt): use install_static::InstallDetails::Get().install_full_name() when
58 // InstallDetails is initialized in the installer. 60 // InstallDetails is initialized in the installer.
59 base::string16 InstallFullName() { 61 base::string16 InstallFullName() {
60 #if defined(GOOGLE_CHROME_BUILD) 62 #if defined(GOOGLE_CHROME_BUILD)
61 base::string16 reg_path(L"Chrome"); 63 base::string16 reg_path(L"Chrome");
62 if (InstallUtil::IsChromeSxSProcess()) 64 if (InstallUtil::IsChromeSxSProcess())
63 reg_path.append(L" SxS"); 65 reg_path.append(L" SxS");
64 return reg_path; 66 return reg_path;
65 #else 67 #else
66 return base::string16(L"Chromium"); 68 return base::string16(L"Chromium");
67 #endif 69 #endif
68 } 70 }
69 71
70 // Returns true if product |type| cam be meaningfully installed without the
71 // --multi-install flag.
72 bool SupportsSingleInstall(BrowserDistribution::Type type) {
73 return (type == BrowserDistribution::CHROME_BROWSER ||
74 type == BrowserDistribution::CHROME_FRAME);
75 }
76
77 // Returns true if the "lastrun" value in |root|\|key_path| (a path to Chrome's 72 // Returns true if the "lastrun" value in |root|\|key_path| (a path to Chrome's
78 // ClientState key for a user) indicates that Chrome has been used within the 73 // ClientState key for a user) indicates that Chrome has been used within the
79 // last 28 days. 74 // last 28 days.
80 bool IsActivelyUsedIn(HKEY root, const wchar_t* key_path) { 75 bool IsActivelyUsedIn(HKEY root, const wchar_t* key_path) {
81 // This duplicates some logic in GoogleUpdateSettings::GetLastRunTime, which 76 // This duplicates some logic in GoogleUpdateSettings::GetLastRunTime, which
82 // is suitable for use from the context of Chrome but not from the installer 77 // is suitable for use from the context of Chrome but not from the installer
83 // because it was implemented with the assumption that 78 // because it was implemented with the assumption that
84 // BrowserDistribution::GetDistribution() will always be the right thing. 79 // BrowserDistribution::GetDistribution() will always be the right thing.
85 // This is true in Chrome, but not in the installer in a multi-install world. 80 // This is true in Chrome, but not in the installer in a multi-install world.
86 // Once multi-install goes away, this assumption will once again become true 81 // Once multi-install goes away, this assumption will once again become true
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 const wchar_t* user_sid, 120 const wchar_t* user_sid,
126 base::win::RegKey* user_hive) { 121 base::win::RegKey* user_hive) {
127 // Continue the iteration if this hive isn't owned by an active Chrome user. 122 // Continue the iteration if this hive isn't owned by an active Chrome user.
128 if (!IsActivelyUsedIn(user_hive->Handle(), client_state_path.c_str())) 123 if (!IsActivelyUsedIn(user_hive->Handle(), client_state_path.c_str()))
129 return true; 124 return true;
130 // Stop the iteration. 125 // Stop the iteration.
131 *is_used = true; 126 *is_used = true;
132 return false; 127 return false;
133 } 128 }
134 129
130 // "The binaries" once referred to the on-disk footprint of Chrome and/or Chrome
131 // Frame when the products were configured to share such on-disk bits. Support
132 // for this mode of install was dropped from ToT in December 2016. Remove any
133 // stray bits in the registry leftover from such installs.
134 void RemoveBinariesVersionKey(const InstallerState& installer_state) {
135 #if defined(GOOGLE_CHROME_BUILD)
136 UpdatingAppRegistrationData reg_data(
137 L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}");
138 #else
139 NonUpdatingAppRegistrationData reg_data(L"Software\\Chromium Binaries");
140 #endif
141
142 base::string16 path(reg_data.GetVersionKey());
143 if (base::win::RegKey(installer_state.root_key(), path.c_str(),
144 KEY_QUERY_VALUE | KEY_WOW64_32KEY)
145 .Valid()) {
146 const bool success = InstallUtil::DeleteRegistryKey(
147 installer_state.root_key(), path, KEY_WOW64_32KEY);
148 UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteBinariesClientsKey", success);
149 }
150 }
151
152 // Remove leftover traces of multi-install Chrome Frame, if present. Once upon a
153 // time, Google Chrome Frame could be co-installed with Chrome such that they
154 // shared the same binaries on disk. Support for new installs of GCF was dropped
155 // from ToT in December 2013. Remove any stray bits in the registry leftover
156 // from an old multi-install GCF.
157 void RemoveMultiChromeFrame(const InstallerState& installer_state) {
158 // There never was a "Chromium Frame".
159 #if defined(GOOGLE_CHROME_BUILD)
160 // To maximize cleanup, unconditionally delete GCF's Clients and ClientState
161 // keys unless single-install GCF is present. This condition is satisfied if
162 // both keys exist, Clients\pv contains a value, and
163 // ClientState\UninstallString contains a path including "\Chrome Frame\".
164 // Multi-install GCF would have had "\Chrome\", and anything else is garbage.
165
166 UpdatingAppRegistrationData gcf_data(
167 L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}");
168 base::win::RegKey clients_key;
169 base::win::RegKey client_state_key;
170
171 const bool has_clients_key =
172 clients_key.Open(installer_state.root_key(),
173 gcf_data.GetVersionKey().c_str(),
174 KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS;
175 const bool has_client_state_key =
176 client_state_key.Open(installer_state.root_key(),
177 gcf_data.GetStateKey().c_str(),
178 KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS;
179 if (!has_clients_key && !has_client_state_key)
180 return; // Nothing to check or to clean.
181
182 base::string16 value;
183 if (has_clients_key && has_client_state_key &&
184 clients_key.ReadValue(google_update::kRegVersionField, &value) ==
185 ERROR_SUCCESS &&
186 !value.empty() &&
187 client_state_key.ReadValue(kUninstallStringField, &value) ==
188 ERROR_SUCCESS &&
189 value.find(L"\\Chrome Frame\\") != base::string16::npos) {
190 return; // Single-install Chrome Frame found.
191 }
192 client_state_key.Close();
193 clients_key.Close();
194
195 // Remnants of multi-install GCF or of a malformed GCF are present. Remove the
196 // Clients and ClientState keys so that Google Update ceases to check for
197 // updates, and the Programs and Features control panel entry to reduce user
198 // confusion.
199 constexpr int kOperations = 3;
200 int success_count = 0;
201
202 if (InstallUtil::DeleteRegistryKey(installer_state.root_key(),
203 gcf_data.GetVersionKey(),
204 KEY_WOW64_32KEY)) {
205 ++success_count;
206 }
207 if (InstallUtil::DeleteRegistryKey(installer_state.root_key(),
208 gcf_data.GetStateKey(), KEY_WOW64_32KEY)) {
209 ++success_count;
210 }
211 if (InstallUtil::DeleteRegistryKey(
212 installer_state.root_key(),
213 L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
214 L"Google Chrome Frame",
215 KEY_WOW64_32KEY)) {
216 ++success_count;
217 }
218 DCHECK_LE(success_count, kOperations);
219
220 // Used for a histogram; do not reorder.
221 enum MultiChromeFrameRemovalResult {
222 ALL_FAILED = 0,
223 PARTIAL_SUCCESS = 1,
224 SUCCESS = 2,
225 NUM_RESULTS
226 };
227 MultiChromeFrameRemovalResult result =
228 (success_count == kOperations ? SUCCESS : (success_count ? PARTIAL_SUCCESS
229 : ALL_FAILED));
230 UMA_HISTOGRAM_ENUMERATION("Setup.Install.MultiChromeFrameRemoved", result,
231 NUM_RESULTS);
232 #endif // GOOGLE_CHROME_BUILD
233 }
234
235 void RemoveAppLauncherVersionKey(const InstallerState& installer_state) {
236 // The app launcher was only registered for Google Chrome.
237 #if defined(GOOGLE_CHROME_BUILD)
238 UpdatingAppRegistrationData reg_data(
239 L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}");
240
241 base::string16 path(reg_data.GetVersionKey());
242 if (base::win::RegKey(installer_state.root_key(), path.c_str(),
243 KEY_QUERY_VALUE | KEY_WOW64_32KEY)
244 .Valid()) {
245 const bool succeeded = InstallUtil::DeleteRegistryKey(
246 installer_state.root_key(), path, KEY_WOW64_32KEY);
247 UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteAppLauncherClientsKey",
248 succeeded);
249 }
250 #endif // GOOGLE_CHROME_BUILD
251 }
252
253 void RemoveAppHostExe(const InstallerState& installer_state) {
254 // The app host was only installed for Google Chrome.
255 #if defined(GOOGLE_CHROME_BUILD)
256 base::FilePath app_host(
257 installer_state.target_path().Append(FILE_PATH_LITERAL("app_host.exe")));
258
259 if (base::PathExists(app_host)) {
260 const bool succeeded = base::DeleteFile(app_host, false);
261 UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteAppHost", succeeded);
262 }
263 #endif // GOOGLE_CHROME_BUILD
264 }
265
266 void RemoveLegacyChromeAppCommands(const InstallerState& installer_state) {
267 // These app commands were only registered for Google Chrome.
268 #if defined(GOOGLE_CHROME_BUILD)
269 base::string16 path(GetRegistrationDataCommandKey(
270 installer_state.product().distribution()->GetAppRegistrationData(),
271 L"install-extension"));
272
273 if (base::win::RegKey(installer_state.root_key(), path.c_str(),
274 KEY_QUERY_VALUE | KEY_WOW64_32KEY)
275 .Valid()) {
276 const bool succeeded = InstallUtil::DeleteRegistryKey(
277 installer_state.root_key(), path, KEY_WOW64_32KEY);
278 UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteInstallExtensionCommand",
279 succeeded);
280 }
281 #endif // GOOGLE_CHROME_BUILD
282 }
283
135 } // namespace 284 } // namespace
136 285
137 const char kUnPackStatusMetricsName[] = "Setup.Install.LzmaUnPackStatus"; 286 const char kUnPackStatusMetricsName[] = "Setup.Install.LzmaUnPackStatus";
138 const char kUnPackNTSTATUSMetricsName[] = "Setup.Install.LzmaUnPackNTSTATUS"; 287 const char kUnPackNTSTATUSMetricsName[] = "Setup.Install.LzmaUnPackNTSTATUS";
139 288
140 int CourgettePatchFiles(const base::FilePath& src, 289 int CourgettePatchFiles(const base::FilePath& src,
141 const base::FilePath& patch, 290 const base::FilePath& patch,
142 const base::FilePath& dest) { 291 const base::FilePath& dest) {
143 VLOG(1) << "Applying Courgette patch " << patch.value() 292 VLOG(1) << "Applying Courgette patch " << patch.value()
144 << " to file " << src.value() 293 << " to file " << src.value()
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 PLOG(ERROR) << "VirtualAllocEx"; 444 PLOG(ERROR) << "VirtualAllocEx";
296 ::TerminateProcess(pi.hProcess, ~static_cast<UINT>(0)); 445 ::TerminateProcess(pi.hProcess, ~static_cast<UINT>(0));
297 } 446 }
298 ::CloseHandle(pi.hThread); 447 ::CloseHandle(pi.hThread);
299 ::CloseHandle(pi.hProcess); 448 ::CloseHandle(pi.hProcess);
300 } 449 }
301 450
302 return ok != FALSE; 451 return ok != FALSE;
303 } 452 }
304 453
305 // There are 4 disjoint cases => return values {false,true}:
306 // (1) Product is being uninstalled => false.
307 // (2) Product is being installed => true.
308 // (3) Current operation ignores product, product is absent => false.
309 // (4) Current operation ignores product, product is present => true.
310 bool WillProductBePresentAfterSetup(
311 const installer::InstallerState& installer_state,
312 const installer::InstallationState& machine_state,
313 BrowserDistribution::Type type) {
314 DCHECK(SupportsSingleInstall(type) || installer_state.is_multi_install());
315
316 const ProductState* product_state =
317 machine_state.GetProductState(installer_state.system_install(), type);
318
319 // Determine if the product is present prior to the current operation.
320 bool is_present = (product_state != NULL);
321 bool is_uninstall = installer_state.operation() == InstallerState::UNINSTALL;
322
323 // Determine if current operation affects the product.
324 const Product* product = installer_state.FindProduct(type);
325 bool is_affected = (product != NULL);
326
327 // Decide among {(1),(2),(3),(4)}.
328 return is_affected ? !is_uninstall : is_present;
329 }
330
331 bool AdjustProcessPriority() { 454 bool AdjustProcessPriority() {
332 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { 455 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
333 DWORD priority_class = ::GetPriorityClass(::GetCurrentProcess()); 456 DWORD priority_class = ::GetPriorityClass(::GetCurrentProcess());
334 if (priority_class == 0) { 457 if (priority_class == 0) {
335 PLOG(WARNING) << "Failed to get the process's priority class."; 458 PLOG(WARNING) << "Failed to get the process's priority class.";
336 } else if (priority_class == BELOW_NORMAL_PRIORITY_CLASS || 459 } else if (priority_class == BELOW_NORMAL_PRIORITY_CLASS ||
337 priority_class == IDLE_PRIORITY_CLASS) { 460 priority_class == IDLE_PRIORITY_CLASS) {
338 BOOL result = ::SetPriorityClass(::GetCurrentProcess(), 461 BOOL result = ::SetPriorityClass(::GetCurrentProcess(),
339 PROCESS_MODE_BACKGROUND_BEGIN); 462 PROCESS_MODE_BACKGROUND_BEGIN);
340 PLOG_IF(WARNING, !result) << "Failed to enter background mode."; 463 PLOG_IF(WARNING, !result) << "Failed to enter background mode.";
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 base::string16 reg_path(kEventLogProvidersRegPath); 848 base::string16 reg_path(kEventLogProvidersRegPath);
726 reg_path.append(InstallFullName()); 849 reg_path.append(InstallFullName());
727 850
728 // TODO(http://crbug.com/668120): If the Event Viewer is open the provider dll 851 // TODO(http://crbug.com/668120): If the Event Viewer is open the provider dll
729 // will fail to get deleted. This doesn't fail the uninstallation altogether 852 // will fail to get deleted. This doesn't fail the uninstallation altogether
730 // but leaves files behind. 853 // but leaves files behind.
731 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path, 854 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path,
732 WorkItem::kWow64Default); 855 WorkItem::kWow64Default);
733 } 856 }
734 857
858 void DoLegacyCleanups(const InstallerState& installer_state,
859 InstallStatus install_status) {
860 // Do no harm if the install didn't succeed.
861 if (InstallUtil::GetInstallReturnCode(install_status))
862 return;
863
864 // The cleanups below only apply to normal Chrome, not side-by-side (canary).
865 if (InstallUtil::IsChromeSxSProcess())
866 return;
867
868 RemoveBinariesVersionKey(installer_state);
869 RemoveMultiChromeFrame(installer_state);
870 RemoveAppLauncherVersionKey(installer_state);
871 RemoveAppHostExe(installer_state);
872 RemoveLegacyChromeAppCommands(installer_state);
873 }
874
735 ScopedTokenPrivilege::ScopedTokenPrivilege(const wchar_t* privilege_name) 875 ScopedTokenPrivilege::ScopedTokenPrivilege(const wchar_t* privilege_name)
736 : is_enabled_(false) { 876 : is_enabled_(false) {
737 HANDLE temp_handle; 877 HANDLE temp_handle;
738 if (!::OpenProcessToken(::GetCurrentProcess(), 878 if (!::OpenProcessToken(::GetCurrentProcess(),
739 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 879 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
740 &temp_handle)) { 880 &temp_handle)) {
741 return; 881 return;
742 } 882 }
743 token_.Set(temp_handle); 883 token_.Set(temp_handle);
744 884
(...skipping 22 matching lines...) Expand all
767 } 907 }
768 908
769 ScopedTokenPrivilege::~ScopedTokenPrivilege() { 909 ScopedTokenPrivilege::~ScopedTokenPrivilege() {
770 if (is_enabled_ && previous_privileges_.PrivilegeCount != 0) { 910 if (is_enabled_ && previous_privileges_.PrivilegeCount != 0) {
771 ::AdjustTokenPrivileges(token_.Get(), FALSE, &previous_privileges_, 911 ::AdjustTokenPrivileges(token_.Get(), FALSE, &previous_privileges_,
772 sizeof(TOKEN_PRIVILEGES), NULL, NULL); 912 sizeof(TOKEN_PRIVILEGES), NULL, NULL);
773 } 913 }
774 } 914 }
775 915
776 } // namespace installer 916 } // namespace installer
OLDNEW
« no previous file with comments | « chrome/installer/setup/setup_util.h ('k') | chrome/installer/setup/setup_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698