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
3 // found in the LICENSE file.
5 #include "chrome/installer/util/google_update_settings.h"
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/threading/thread_restrictions.h"
19 #include "base/time/time.h"
20 #include "base/win/registry.h"
21 #include "base/win/win_util.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/installer/util/app_registration_data.h"
24 #include "chrome/installer/util/browser_distribution.h"
25 #include "chrome/installer/util/channel_info.h"
26 #include "chrome/installer/util/google_update_constants.h"
27 #include "chrome/installer/util/install_util.h"
28 #include "chrome/installer/util/installation_state.h"
29 #include "chrome/installer/util/product.h"
31 using base::win::RegKey
;
32 using installer::InstallationState
;
34 const wchar_t GoogleUpdateSettings::kPoliciesKey
[] =
35 L
"SOFTWARE\\Policies\\Google\\Update";
36 const wchar_t GoogleUpdateSettings::kUpdatePolicyValue
[] = L
"UpdateDefault";
37 const wchar_t GoogleUpdateSettings::kUpdateOverrideValuePrefix
[] = L
"Update";
38 const wchar_t GoogleUpdateSettings::kCheckPeriodOverrideMinutes
[] =
39 L
"AutoUpdateCheckPeriodMinutes";
41 // Don't allow update periods longer than six weeks.
42 const int GoogleUpdateSettings::kCheckPeriodOverrideMinutesMax
=
45 const GoogleUpdateSettings::UpdatePolicy
46 GoogleUpdateSettings::kDefaultUpdatePolicy
=
47 #if defined(GOOGLE_CHROME_BUILD)
48 GoogleUpdateSettings::AUTOMATIC_UPDATES
;
50 GoogleUpdateSettings::UPDATES_DISABLED
;
55 bool ReadGoogleUpdateStrKey(const wchar_t* const name
, base::string16
* value
) {
56 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
57 base::string16 reg_path
= dist
->GetStateKey();
58 RegKey
key(HKEY_CURRENT_USER
, reg_path
.c_str(), KEY_READ
| KEY_WOW64_32KEY
);
59 if (key
.ReadValue(name
, value
) != ERROR_SUCCESS
) {
61 HKEY_LOCAL_MACHINE
, reg_path
.c_str(), KEY_READ
| KEY_WOW64_32KEY
);
62 return (hklm_key
.ReadValue(name
, value
) == ERROR_SUCCESS
);
67 // Writes |value| into a user-specific value in the key |name| under
68 // |app_reg_data|'s ClientStateMedium key in HKLM along with the aggregation
69 // method |aggregate|. This function is solely for use by system-level installs.
70 bool WriteGoogleUpdateAggregateNumKeyInternal(
71 const AppRegistrationData
& app_reg_data
,
72 const wchar_t* const name
,
74 const wchar_t* const aggregate
) {
76 DCHECK(GoogleUpdateSettings::IsSystemInstall());
77 const REGSAM kAccess
= KEY_SET_VALUE
| KEY_WOW64_32KEY
;
79 // Machine installs require each OS user to write a unique key under a
80 // named key in HKLM as well as an "aggregation" function that describes
81 // how the values of multiple users are to be combined.
82 base::string16 uniquename
;
83 if (!base::win::GetUserSidString(&uniquename
)) {
88 base::string16
reg_path(app_reg_data
.GetStateMediumKey());
89 reg_path
.append(L
"\\");
90 reg_path
.append(name
);
91 RegKey
key(HKEY_LOCAL_MACHINE
, reg_path
.c_str(), kAccess
);
92 key
.WriteValue(google_update::kRegAggregateMethod
, aggregate
);
94 DWORD dword_value
= (value
> std::numeric_limits
<DWORD
>::max() ?
95 std::numeric_limits
<DWORD
>::max() :
96 static_cast<DWORD
>(value
));
97 return (key
.WriteValue(uniquename
.c_str(), dword_value
) == ERROR_SUCCESS
);
100 // Updates a registry key |name| to be |value| for the given |app_reg_data|.
101 bool WriteGoogleUpdateStrKeyInternal(const AppRegistrationData
& app_reg_data
,
102 const wchar_t* const name
,
103 const base::string16
& value
) {
104 const REGSAM kAccess
= KEY_SET_VALUE
| KEY_WOW64_32KEY
;
105 RegKey
key(HKEY_CURRENT_USER
, app_reg_data
.GetStateKey().c_str(), kAccess
);
106 return (key
.WriteValue(name
, value
.c_str()) == ERROR_SUCCESS
);
109 bool WriteGoogleUpdateStrKey(const wchar_t* const name
,
110 const base::string16
& value
) {
111 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
112 return WriteGoogleUpdateStrKeyInternal(
113 dist
->GetAppRegistrationData(), name
, value
);
116 bool ClearGoogleUpdateStrKey(const wchar_t* const name
) {
117 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
118 base::string16 reg_path
= dist
->GetStateKey();
119 RegKey
key(HKEY_CURRENT_USER
,
121 KEY_READ
| KEY_WRITE
| KEY_WOW64_32KEY
);
122 base::string16 value
;
123 if (key
.ReadValue(name
, &value
) != ERROR_SUCCESS
)
125 return (key
.WriteValue(name
, L
"") == ERROR_SUCCESS
);
128 bool RemoveGoogleUpdateStrKey(const wchar_t* const name
) {
129 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
130 base::string16 reg_path
= dist
->GetStateKey();
131 RegKey
key(HKEY_CURRENT_USER
,
133 KEY_READ
| KEY_WRITE
| KEY_WOW64_32KEY
);
134 if (!key
.HasValue(name
))
136 return (key
.DeleteValue(name
) == ERROR_SUCCESS
);
139 bool GetChromeChannelInternal(bool system_install
,
140 bool add_multi_modifier
,
141 base::string16
* channel
) {
142 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
144 // Shortcut in case this distribution knows what channel it is (canary).
145 if (dist
->GetChromeChannel(channel
))
148 // Determine whether or not chrome is multi-install. If so, updates are
149 // delivered under the binaries' app guid, so that's where the relevant
151 installer::ProductState state
;
152 installer::ChannelInfo channel_info
;
153 ignore_result(state
.Initialize(system_install
, dist
));
154 if (!state
.is_multi_install()) {
155 // Use the channel info that was just read for this single-install chrome.
156 channel_info
= state
.channel();
158 // Read the channel info from the binaries' state key.
159 HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
160 dist
= BrowserDistribution::GetSpecificDistribution(
161 BrowserDistribution::CHROME_BINARIES
);
162 RegKey
key(root_key
, dist
->GetStateKey().c_str(),
163 KEY_READ
| KEY_WOW64_32KEY
);
165 if (!channel_info
.Initialize(key
)) {
166 channel
->assign(installer::kChromeChannelUnknown
);
171 if (!channel_info
.GetChannelName(channel
))
172 channel
->assign(installer::kChromeChannelUnknown
);
174 // Tag the channel name if this is a multi-install.
175 if (add_multi_modifier
&& state
.is_multi_install()) {
176 if (!channel
->empty())
177 channel
->push_back(L
'-');
178 channel
->push_back(L
'm');
184 #if defined(GOOGLE_CHROME_BUILD)
185 // Populates |update_policy| with the UpdatePolicy enum value corresponding to a
186 // DWORD read from the registry and returns true if |value| is within range.
187 // If |value| is out of range, returns false without modifying |update_policy|.
188 bool GetUpdatePolicyFromDword(
190 GoogleUpdateSettings::UpdatePolicy
* update_policy
) {
192 case GoogleUpdateSettings::UPDATES_DISABLED
:
193 case GoogleUpdateSettings::AUTOMATIC_UPDATES
:
194 case GoogleUpdateSettings::MANUAL_UPDATES_ONLY
:
195 case GoogleUpdateSettings::AUTO_UPDATES_ONLY
:
196 *update_policy
= static_cast<GoogleUpdateSettings::UpdatePolicy
>(value
);
199 LOG(WARNING
) << "Unexpected update policy override value: " << value
;
203 #endif // defined(GOOGLE_CHROME_BUILD)
205 // Convenience routine: GoogleUpdateSettings::UpdateDidRunStateForApp()
206 // specialized for Chrome Binaries.
207 bool UpdateDidRunStateForBinaries(bool did_run
) {
208 BrowserDistribution
* dist
= BrowserDistribution::GetSpecificDistribution(
209 BrowserDistribution::CHROME_BINARIES
);
210 return GoogleUpdateSettings::UpdateDidRunStateForApp(
211 dist
->GetAppRegistrationData(), did_run
);
216 bool GoogleUpdateSettings::IsSystemInstall() {
217 bool system_install
= false;
218 base::FilePath module_dir
;
219 if (!PathService::Get(base::DIR_MODULE
, &module_dir
)) {
221 << "Failed to get directory of module; assuming per-user install.";
223 system_install
= !InstallUtil::IsPerUserInstall(module_dir
);
225 return system_install
;
228 bool GoogleUpdateSettings::GetCollectStatsConsent() {
229 return GetCollectStatsConsentAtLevel(IsSystemInstall());
232 // Older versions of Chrome unconditionally read from HKCU\...\ClientState\...
233 // and then HKLM\...\ClientState\.... This means that system-level Chrome
234 // never checked ClientStateMedium (which has priority according to Google
235 // Update) and gave preference to a value in HKCU (which was never checked by
236 // Google Update). From now on, Chrome follows Google Update's policy.
237 bool GoogleUpdateSettings::GetCollectStatsConsentAtLevel(bool system_install
) {
238 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
240 // Consent applies to all products in a multi-install package.
241 if (InstallUtil::IsMultiInstall(dist
, system_install
)) {
242 dist
= BrowserDistribution::GetSpecificDistribution(
243 BrowserDistribution::CHROME_BINARIES
);
248 bool have_value
= false;
249 const REGSAM kAccess
= KEY_QUERY_VALUE
| KEY_WOW64_32KEY
;
251 // For system-level installs, try ClientStateMedium first.
254 key
.Open(HKEY_LOCAL_MACHINE
, dist
->GetStateMediumKey().c_str(),
255 kAccess
) == ERROR_SUCCESS
&&
256 key
.ReadValueDW(google_update::kRegUsageStatsField
,
257 &value
) == ERROR_SUCCESS
;
259 // Otherwise, try ClientState.
262 key
.Open(system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
263 dist
->GetStateKey().c_str(),
264 kAccess
) == ERROR_SUCCESS
&&
265 key
.ReadValueDW(google_update::kRegUsageStatsField
,
266 &value
) == ERROR_SUCCESS
;
269 // Google Update specifically checks that the value is 1, so we do the same.
270 return have_value
&& value
== 1;
273 bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented
) {
274 return SetCollectStatsConsentAtLevel(IsSystemInstall(), consented
);
277 bool GoogleUpdateSettings::SetCollectStatsConsentAtLevel(bool system_install
,
279 // Google Update writes and expects 1 for true, 0 for false.
280 DWORD value
= consented
? 1 : 0;
282 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
284 // Consent applies to all products in a multi-install package.
285 if (InstallUtil::IsMultiInstall(dist
, system_install
)) {
286 dist
= BrowserDistribution::GetSpecificDistribution(
287 BrowserDistribution::CHROME_BINARIES
);
290 // Write to ClientStateMedium for system-level; ClientState otherwise.
291 HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
292 base::string16 reg_path
=
293 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey();
295 LONG result
= key
.Create(
296 root_key
, reg_path
.c_str(), KEY_SET_VALUE
| KEY_WOW64_32KEY
);
297 if (result
!= ERROR_SUCCESS
) {
298 LOG(ERROR
) << "Failed opening key " << reg_path
<< " to set "
299 << google_update::kRegUsageStatsField
<< "; result: " << result
;
301 result
= key
.WriteValue(google_update::kRegUsageStatsField
, value
);
302 LOG_IF(ERROR
, result
!= ERROR_SUCCESS
) << "Failed setting "
303 << google_update::kRegUsageStatsField
<< " in key " << reg_path
304 << "; result: " << result
;
306 return (result
== ERROR_SUCCESS
);
309 scoped_ptr
<metrics::ClientInfo
> GoogleUpdateSettings::LoadMetricsClientInfo() {
310 base::string16 client_id_16
;
311 if (!ReadGoogleUpdateStrKey(google_update::kRegMetricsId
, &client_id_16
) ||
312 client_id_16
.empty()) {
313 return scoped_ptr
<metrics::ClientInfo
>();
316 scoped_ptr
<metrics::ClientInfo
> client_info(new metrics::ClientInfo
);
317 client_info
->client_id
= base::UTF16ToUTF8(client_id_16
);
319 base::string16 installation_date_str
;
320 if (ReadGoogleUpdateStrKey(google_update::kRegMetricsIdInstallDate
,
321 &installation_date_str
)) {
322 base::StringToInt64(installation_date_str
, &client_info
->installation_date
);
325 base::string16 reporting_enbaled_date_date_str
;
326 if (ReadGoogleUpdateStrKey(google_update::kRegMetricsIdEnabledDate
,
327 &reporting_enbaled_date_date_str
)) {
328 base::StringToInt64(reporting_enbaled_date_date_str
,
329 &client_info
->reporting_enabled_date
);
332 return client_info
.Pass();
335 void GoogleUpdateSettings::StoreMetricsClientInfo(
336 const metrics::ClientInfo
& client_info
) {
337 // Attempt a best-effort at backing |client_info| in the registry (but don't
338 // handle/report failures).
339 WriteGoogleUpdateStrKey(google_update::kRegMetricsId
,
340 base::UTF8ToUTF16(client_info
.client_id
));
341 WriteGoogleUpdateStrKey(google_update::kRegMetricsIdInstallDate
,
342 base::Int64ToString16(client_info
.installation_date
));
343 WriteGoogleUpdateStrKey(
344 google_update::kRegMetricsIdEnabledDate
,
345 base::Int64ToString16(client_info
.reporting_enabled_date
));
348 // EULA consent is only relevant for system-level installs.
349 bool GoogleUpdateSettings::SetEULAConsent(
350 const InstallationState
& machine_state
,
351 BrowserDistribution
* dist
,
354 const DWORD eula_accepted
= consented
? 1 : 0;
355 const REGSAM kAccess
= KEY_SET_VALUE
| KEY_WOW64_32KEY
;
356 base::string16 reg_path
= dist
->GetStateMediumKey();
357 bool succeeded
= true;
360 // Write the consent value into the product's ClientStateMedium key.
361 if (key
.Create(HKEY_LOCAL_MACHINE
, reg_path
.c_str(),
362 kAccess
) != ERROR_SUCCESS
||
363 key
.WriteValue(google_update::kRegEULAAceptedField
,
364 eula_accepted
) != ERROR_SUCCESS
) {
368 // If this is a multi-install, also write it into the binaries' key.
369 // --mutli-install is not provided on the command-line, so deduce it from
370 // the product's state.
371 const installer::ProductState
* product_state
=
372 machine_state
.GetProductState(true, dist
->GetType());
373 if (product_state
!= NULL
&& product_state
->is_multi_install()) {
374 dist
= BrowserDistribution::GetSpecificDistribution(
375 BrowserDistribution::CHROME_BINARIES
);
376 reg_path
= dist
->GetStateMediumKey();
377 if (key
.Create(HKEY_LOCAL_MACHINE
, reg_path
.c_str(),
378 kAccess
) != ERROR_SUCCESS
||
379 key
.WriteValue(google_update::kRegEULAAceptedField
,
380 eula_accepted
) != ERROR_SUCCESS
) {
388 int GoogleUpdateSettings::GetLastRunTime() {
389 base::string16 time_s
;
390 if (!ReadGoogleUpdateStrKey(google_update::kRegLastRunTimeField
, &time_s
))
393 if (!base::StringToInt64(time_s
, &time_i
))
396 base::Time::NowFromSystemTime() - base::Time::FromInternalValue(time_i
);
400 bool GoogleUpdateSettings::SetLastRunTime() {
401 int64 time
= base::Time::NowFromSystemTime().ToInternalValue();
402 return WriteGoogleUpdateStrKey(google_update::kRegLastRunTimeField
,
403 base::Int64ToString16(time
));
406 bool GoogleUpdateSettings::RemoveLastRunTime() {
407 return RemoveGoogleUpdateStrKey(google_update::kRegLastRunTimeField
);
410 bool GoogleUpdateSettings::GetBrowser(base::string16
* browser
) {
411 return ReadGoogleUpdateStrKey(google_update::kRegBrowserField
, browser
);
414 bool GoogleUpdateSettings::GetLanguage(base::string16
* language
) {
415 return ReadGoogleUpdateStrKey(google_update::kRegLangField
, language
);
418 bool GoogleUpdateSettings::GetBrand(base::string16
* brand
) {
419 return ReadGoogleUpdateStrKey(google_update::kRegRLZBrandField
, brand
);
422 bool GoogleUpdateSettings::GetReactivationBrand(base::string16
* brand
) {
423 return ReadGoogleUpdateStrKey(google_update::kRegRLZReactivationBrandField
,
427 bool GoogleUpdateSettings::GetClient(base::string16
* client
) {
428 return ReadGoogleUpdateStrKey(google_update::kRegClientField
, client
);
431 bool GoogleUpdateSettings::SetClient(const base::string16
& client
) {
432 return WriteGoogleUpdateStrKey(google_update::kRegClientField
, client
);
435 bool GoogleUpdateSettings::GetReferral(base::string16
* referral
) {
436 return ReadGoogleUpdateStrKey(google_update::kRegReferralField
, referral
);
439 bool GoogleUpdateSettings::ClearReferral() {
440 return ClearGoogleUpdateStrKey(google_update::kRegReferralField
);
443 bool GoogleUpdateSettings::UpdateDidRunStateForApp(
444 const AppRegistrationData
& app_reg_data
,
446 return WriteGoogleUpdateStrKeyInternal(app_reg_data
,
447 google_update::kRegDidRunField
,
448 did_run
? L
"1" : L
"0");
451 bool GoogleUpdateSettings::UpdateDidRunState(bool did_run
, bool system_level
) {
452 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
453 bool result
= UpdateDidRunStateForApp(dist
->GetAppRegistrationData(),
455 // Update state for binaries, even if the previous call was unsuccessful.
456 if (InstallUtil::IsMultiInstall(dist
, system_level
))
457 result
= UpdateDidRunStateForBinaries(did_run
) && result
;
461 base::string16
GoogleUpdateSettings::GetChromeChannel(bool system_install
) {
462 base::string16 channel
;
463 GetChromeChannelInternal(system_install
, false, &channel
);
467 bool GoogleUpdateSettings::GetChromeChannelAndModifiers(
469 base::string16
* channel
) {
470 return GetChromeChannelInternal(system_install
, true, channel
);
473 void GoogleUpdateSettings::UpdateInstallStatus(bool system_install
,
474 installer::ArchiveType archive_type
, int install_return_code
,
475 const base::string16
& product_guid
) {
476 DCHECK(archive_type
!= installer::UNKNOWN_ARCHIVE_TYPE
||
477 install_return_code
!= 0);
478 HKEY reg_root
= (system_install
) ? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
481 installer::ChannelInfo channel_info
;
482 base::string16
reg_key(google_update::kRegPathClientState
);
483 reg_key
.append(L
"\\");
484 reg_key
.append(product_guid
);
485 LONG result
= key
.Open(reg_root
,
487 KEY_QUERY_VALUE
| KEY_SET_VALUE
| KEY_WOW64_32KEY
);
488 if (result
== ERROR_SUCCESS
)
489 channel_info
.Initialize(key
);
490 else if (result
!= ERROR_FILE_NOT_FOUND
)
491 LOG(ERROR
) << "Failed to open " << reg_key
<< "; Error: " << result
;
493 if (UpdateGoogleUpdateApKey(archive_type
, install_return_code
,
495 // We have a modified channel_info value to write.
496 // Create the app's ClientState key if it doesn't already exist.
498 result
= key
.Open(reg_root
,
499 google_update::kRegPathClientState
,
500 KEY_CREATE_SUB_KEY
| KEY_WOW64_32KEY
);
501 if (result
== ERROR_SUCCESS
)
502 result
= key
.CreateKey(product_guid
.c_str(),
503 KEY_SET_VALUE
| KEY_WOW64_32KEY
);
505 if (result
!= ERROR_SUCCESS
) {
506 LOG(ERROR
) << "Failed to create " << reg_key
<< "; Error: " << result
;
510 if (!channel_info
.Write(&key
)) {
511 LOG(ERROR
) << "Failed to write to application's ClientState key "
512 << google_update::kRegApField
<< " = " << channel_info
.value();
517 bool GoogleUpdateSettings::UpdateGoogleUpdateApKey(
518 installer::ArchiveType archive_type
, int install_return_code
,
519 installer::ChannelInfo
* value
) {
520 DCHECK(archive_type
!= installer::UNKNOWN_ARCHIVE_TYPE
||
521 install_return_code
!= 0);
522 bool modified
= false;
524 if (archive_type
== installer::FULL_ARCHIVE_TYPE
|| !install_return_code
) {
525 if (value
->SetFullSuffix(false)) {
526 VLOG(1) << "Removed incremental installer failure key; "
527 "switching to channel: "
531 } else if (archive_type
== installer::INCREMENTAL_ARCHIVE_TYPE
) {
532 if (value
->SetFullSuffix(true)) {
533 VLOG(1) << "Incremental installer failed; switching to channel: "
537 VLOG(1) << "Incremental installer failure; already on channel: "
541 // It's okay if we don't know the archive type. In this case, leave the
542 // "-full" suffix as we found it.
543 DCHECK_EQ(installer::UNKNOWN_ARCHIVE_TYPE
, archive_type
);
546 if (value
->SetMultiFailSuffix(false)) {
547 VLOG(1) << "Removed multi-install failure key; switching to channel: "
555 void GoogleUpdateSettings::UpdateProfileCounts(size_t profiles_active
,
556 size_t profiles_signedin
) {
557 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
558 // System-level installs must write into the ClientStateMedium key shared by
559 // all users. Special treatment is used to aggregate across those users.
560 if (IsSystemInstall()) {
561 // Write the counts as ints that get aggregated across all users via
562 // summation for system-level installs.
563 WriteGoogleUpdateAggregateNumKeyInternal(
564 dist
->GetAppRegistrationData(),
565 google_update::kRegProfilesActive
,
568 WriteGoogleUpdateAggregateNumKeyInternal(
569 dist
->GetAppRegistrationData(),
570 google_update::kRegProfilesSignedIn
,
574 // Write the counts as strings since no aggregation function is needed for
575 // user-level installs.
576 WriteGoogleUpdateStrKeyInternal(dist
->GetAppRegistrationData(),
577 google_update::kRegProfilesActive
,
578 base::SizeTToString16(profiles_active
));
579 WriteGoogleUpdateStrKeyInternal(dist
->GetAppRegistrationData(),
580 google_update::kRegProfilesSignedIn
,
581 base::SizeTToString16(profiles_signedin
));
585 int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() {
586 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
587 base::string16 reg_path
= dist
->GetStateKey();
589 // Minimum access needed is to be able to write to this key.
591 HKEY_LOCAL_MACHINE
, reg_path
.c_str(), KEY_SET_VALUE
| KEY_WOW64_32KEY
);
592 if (!reg_key
.Valid())
595 HANDLE target_handle
= 0;
596 if (!DuplicateHandle(GetCurrentProcess(), reg_key
.Handle(),
597 GetCurrentProcess(), &target_handle
, KEY_SET_VALUE
,
598 TRUE
, DUPLICATE_SAME_ACCESS
)) {
601 return static_cast<int>(reinterpret_cast<uintptr_t>(target_handle
));
604 bool GoogleUpdateSettings::WriteGoogleUpdateSystemClientKey(
605 int handle
, const base::string16
& key
, const base::string16
& value
) {
606 HKEY reg_key
= reinterpret_cast<HKEY
>(
607 reinterpret_cast<void*>(static_cast<uintptr_t>(handle
)));
608 DWORD size
= static_cast<DWORD
>(value
.size()) * sizeof(wchar_t);
609 LSTATUS status
= RegSetValueEx(reg_key
, key
.c_str(), 0, REG_SZ
,
610 reinterpret_cast<const BYTE
*>(value
.c_str()), size
);
611 return status
== ERROR_SUCCESS
;
614 GoogleUpdateSettings::UpdatePolicy
GoogleUpdateSettings::GetAppUpdatePolicy(
615 const base::string16
& app_guid
,
616 bool* is_overridden
) {
617 bool found_override
= false;
618 UpdatePolicy update_policy
= kDefaultUpdatePolicy
;
620 #if defined(GOOGLE_CHROME_BUILD)
621 DCHECK(!app_guid
.empty());
624 // Google Update Group Policy settings are always in HKLM.
625 // TODO(wfh): Check if policies should go into Wow6432Node or not.
626 if (policy_key
.Open(HKEY_LOCAL_MACHINE
, kPoliciesKey
, KEY_QUERY_VALUE
) ==
629 base::string16
app_update_override(kUpdateOverrideValuePrefix
);
630 app_update_override
.append(app_guid
);
631 // First try to read and comprehend the app-specific override.
632 found_override
= (policy_key
.ReadValueDW(app_update_override
.c_str(),
633 &value
) == ERROR_SUCCESS
&&
634 GetUpdatePolicyFromDword(value
, &update_policy
));
636 // Failing that, try to read and comprehend the default override.
637 if (!found_override
&&
638 policy_key
.ReadValueDW(kUpdatePolicyValue
, &value
) == ERROR_SUCCESS
) {
639 GetUpdatePolicyFromDword(value
, &update_policy
);
642 #endif // defined(GOOGLE_CHROME_BUILD)
644 if (is_overridden
!= NULL
)
645 *is_overridden
= found_override
;
647 return update_policy
;
651 bool GoogleUpdateSettings::AreAutoupdatesEnabled() {
652 #if defined(GOOGLE_CHROME_BUILD)
653 // Check the auto-update check period override. If it is 0 or exceeds the
654 // maximum timeout, then for all intents and purposes auto updates are
658 if (policy_key
.Open(HKEY_LOCAL_MACHINE
, kPoliciesKey
,
659 KEY_QUERY_VALUE
) == ERROR_SUCCESS
&&
660 policy_key
.ReadValueDW(kCheckPeriodOverrideMinutes
,
661 &value
) == ERROR_SUCCESS
&&
662 (value
== 0 || value
> kCheckPeriodOverrideMinutesMax
)) {
666 // Auto updates are subtly broken when Chrome and the binaries have different
667 // overrides in place. If this Chrome cannot possibly be multi-install by
668 // virtue of being a side-by-side installation, simply check Chrome's policy.
669 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
670 UpdatePolicy app_policy
= GetAppUpdatePolicy(dist
->GetAppGuid(), nullptr);
671 if (InstallUtil::IsChromeSxSProcess())
672 return app_policy
== AUTOMATIC_UPDATES
|| app_policy
== AUTO_UPDATES_ONLY
;
674 // Otherwise, check for consistency between Chrome and the binaries regardless
675 // of whether or not this Chrome is multi-install since the next update likely
676 // will attempt to migrate it to such.
677 BrowserDistribution
* binaries
= BrowserDistribution::GetSpecificDistribution(
678 BrowserDistribution::CHROME_BINARIES
);
679 return (GetAppUpdatePolicy(binaries
->GetAppGuid(), nullptr) == app_policy
&&
680 (app_policy
== AUTOMATIC_UPDATES
|| app_policy
== AUTO_UPDATES_ONLY
));
681 #else // defined(GOOGLE_CHROME_BUILD)
682 // Chromium does not auto update.
684 #endif // !defined(GOOGLE_CHROME_BUILD)
688 bool GoogleUpdateSettings::ReenableAutoupdates() {
689 #if defined(GOOGLE_CHROME_BUILD)
690 int needs_reset_count
= 0;
691 int did_reset_count
= 0;
693 // Reset overrides for Chrome and for the binaries if this Chrome supports
695 std::vector
<base::string16
> app_guids
;
696 app_guids
.push_back(BrowserDistribution::GetDistribution()->GetAppGuid());
697 if (!InstallUtil::IsChromeSxSProcess()) {
698 app_guids
.push_back(BrowserDistribution::GetSpecificDistribution(
699 BrowserDistribution::CHROME_BINARIES
)->GetAppGuid());
702 UpdatePolicy update_policy
= kDefaultUpdatePolicy
;
704 if (policy_key
.Open(HKEY_LOCAL_MACHINE
, kPoliciesKey
,
705 KEY_SET_VALUE
| KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
706 // Set to true while app-specific overrides are present that allow automatic
707 // updates. When this is the case, the defaults are irrelevant and don't
708 // need to be checked or reset.
709 bool automatic_updates_allowed_by_overrides
= true;
711 for (const base::string16
& app_guid
: app_guids
) {
712 // First check the app-specific override value and reset that if needed.
713 // Note that this intentionally sets the override to AUTOMATIC_UPDATES
714 // even if it was previously AUTO_UPDATES_ONLY. The thinking is that
715 // AUTOMATIC_UPDATES is marginally more likely to let a user update and
716 // this code is only called when a stuck user asks for updates.
717 base::string16
app_update_override(kUpdateOverrideValuePrefix
);
718 app_update_override
.append(app_guid
);
719 if (policy_key
.ReadValueDW(app_update_override
.c_str(),
720 &value
) != ERROR_SUCCESS
) {
721 automatic_updates_allowed_by_overrides
= false;
722 } else if (!GetUpdatePolicyFromDword(value
, &update_policy
) ||
723 update_policy
!= GoogleUpdateSettings::AUTOMATIC_UPDATES
) {
724 automatic_updates_allowed_by_overrides
= false;
726 if (policy_key
.WriteValue(
727 app_update_override
.c_str(),
728 static_cast<DWORD
>(GoogleUpdateSettings::AUTOMATIC_UPDATES
)) ==
735 // If there were no app-specific override policies, see if there's a global
736 // policy preventing updates and delete it if so.
737 if (!automatic_updates_allowed_by_overrides
&&
738 policy_key
.ReadValueDW(kUpdatePolicyValue
, &value
) == ERROR_SUCCESS
&&
739 (!GetUpdatePolicyFromDword(value
, &update_policy
) ||
740 update_policy
!= GoogleUpdateSettings::AUTOMATIC_UPDATES
)) {
742 if (policy_key
.DeleteValue(kUpdatePolicyValue
) == ERROR_SUCCESS
)
746 // Check the auto-update check period override. If it is 0 or exceeds
747 // the maximum timeout, delete the override value.
748 if (policy_key
.ReadValueDW(kCheckPeriodOverrideMinutes
,
749 &value
) == ERROR_SUCCESS
&&
750 (value
== 0 || value
> kCheckPeriodOverrideMinutesMax
)) {
752 if (policy_key
.DeleteValue(kCheckPeriodOverrideMinutes
) == ERROR_SUCCESS
)
756 // Return whether the number of successful resets is the same as the
757 // number of things that appeared to need resetting.
758 return (needs_reset_count
== did_reset_count
);
760 // For some reason we couldn't open the policy key with the desired
761 // permissions to make changes (the most likely reason is that there is no
762 // policy set). Simply return whether or not we think updates are enabled.
763 return AreAutoupdatesEnabled();
767 // Non Google Chrome isn't going to autoupdate.
771 void GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms() {
772 const bool is_multi_install
= InstallUtil::IsMultiInstall(
773 BrowserDistribution::GetDistribution(), IsSystemInstall());
774 const base::string16 app_guid
=
775 BrowserDistribution::GetSpecificDistribution(
776 is_multi_install
? BrowserDistribution::CHROME_BINARIES
:
777 BrowserDistribution::CHROME_BROWSER
)->GetAppGuid();
779 bool is_overridden
= false;
780 const UpdatePolicy update_policy
= GetAppUpdatePolicy(app_guid
,
782 UMA_HISTOGRAM_BOOLEAN("GoogleUpdate.UpdatePolicyIsOverridden", is_overridden
);
783 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.EffectivePolicy", update_policy
,
784 UPDATE_POLICIES_COUNT
);
787 base::string16
GoogleUpdateSettings::GetUninstallCommandLine(
788 bool system_install
) {
789 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
790 base::string16 cmd_line
;
793 if (update_key
.Open(root_key
, google_update::kRegPathGoogleUpdate
,
794 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
) == ERROR_SUCCESS
) {
795 update_key
.ReadValue(google_update::kRegUninstallCmdLine
, &cmd_line
);
801 Version
GoogleUpdateSettings::GetGoogleUpdateVersion(bool system_install
) {
802 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
803 base::string16 version
;
806 if (key
.Open(root_key
,
807 google_update::kRegPathGoogleUpdate
,
808 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
) == ERROR_SUCCESS
&&
809 key
.ReadValue(google_update::kRegGoogleUpdateVersion
, &version
) ==
811 return Version(base::UTF16ToUTF8(version
));
817 base::Time
GoogleUpdateSettings::GetGoogleUpdateLastStartedAU(
818 bool system_install
) {
819 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
822 if (update_key
.Open(root_key
,
823 google_update::kRegPathGoogleUpdate
,
824 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
) == ERROR_SUCCESS
) {
826 if (update_key
.ReadValueDW(google_update::kRegLastStartedAUField
,
827 &last_start
) == ERROR_SUCCESS
) {
828 return base::Time::FromTimeT(last_start
);
835 base::Time
GoogleUpdateSettings::GetGoogleUpdateLastChecked(
836 bool system_install
) {
837 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
840 if (update_key
.Open(root_key
,
841 google_update::kRegPathGoogleUpdate
,
842 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
) == ERROR_SUCCESS
) {
844 if (update_key
.ReadValueDW(google_update::kRegLastCheckedField
,
845 &last_check
) == ERROR_SUCCESS
) {
846 return base::Time::FromTimeT(last_check
);
853 bool GoogleUpdateSettings::GetUpdateDetailForApp(bool system_install
,
854 const wchar_t* app_guid
,
859 bool product_found
= false;
861 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
862 base::string16
clientstate_reg_path(google_update::kRegPathClientState
);
863 clientstate_reg_path
.append(L
"\\");
864 clientstate_reg_path
.append(app_guid
);
867 if (clientstate
.Open(root_key
,
868 clientstate_reg_path
.c_str(),
869 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
) == ERROR_SUCCESS
) {
870 base::string16 version
;
872 if ((clientstate
.ReadValueDW(google_update::kRegLastCheckSuccessField
,
873 &dword_value
) == ERROR_SUCCESS
) &&
874 (clientstate
.ReadValue(google_update::kRegVersionField
,
875 &version
) == ERROR_SUCCESS
)) {
876 product_found
= true;
877 data
->version
= base::UTF16ToASCII(version
);
878 data
->last_success
= base::Time::FromTimeT(dword_value
);
879 data
->last_result
= 0;
880 data
->last_error_code
= 0;
881 data
->last_extra_code
= 0;
883 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerResultField
,
884 &dword_value
) == ERROR_SUCCESS
) {
885 // Google Update convention is that if an installer writes an result
886 // code that is invalid, it is clamped to an exit code result.
887 const DWORD kMaxValidInstallResult
= 4; // INSTALLER_RESULT_EXIT_CODE
888 data
->last_result
= std::min(dword_value
, kMaxValidInstallResult
);
890 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerErrorField
,
891 &dword_value
) == ERROR_SUCCESS
) {
892 data
->last_error_code
= dword_value
;
894 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerExtraField
,
895 &dword_value
) == ERROR_SUCCESS
) {
896 data
->last_extra_code
= dword_value
;
901 return product_found
;
904 bool GoogleUpdateSettings::GetUpdateDetailForGoogleUpdate(bool system_install
,
906 return GetUpdateDetailForApp(system_install
,
907 google_update::kGoogleUpdateUpgradeCode
,
911 bool GoogleUpdateSettings::GetUpdateDetail(bool system_install
,
913 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
914 return GetUpdateDetailForApp(system_install
,
915 dist
->GetAppGuid().c_str(),
919 bool GoogleUpdateSettings::SetExperimentLabels(
921 const base::string16
& experiment_labels
) {
922 HKEY reg_root
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
924 // Use the browser distribution and install level to write to the correct
925 // client state/app guid key.
926 bool success
= false;
927 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
928 if (dist
->ShouldSetExperimentLabels()) {
929 base::string16
client_state_path(
930 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey());
932 reg_root
, client_state_path
.c_str(), KEY_SET_VALUE
| KEY_WOW64_32KEY
);
933 // It is possible that the registry keys do not yet exist or have not yet
934 // been ACLed by Google Update to be user writable.
935 if (!client_state
.Valid())
937 if (experiment_labels
.empty()) {
938 success
= client_state
.DeleteValue(google_update::kExperimentLabels
)
941 success
= client_state
.WriteValue(google_update::kExperimentLabels
,
942 experiment_labels
.c_str()) == ERROR_SUCCESS
;
949 bool GoogleUpdateSettings::ReadExperimentLabels(
951 base::string16
* experiment_labels
) {
952 HKEY reg_root
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
954 // If this distribution does not set the experiment labels, don't bother
956 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
957 if (!dist
->ShouldSetExperimentLabels())
960 base::string16
client_state_path(
961 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey());
964 LONG result
= client_state
.Open(
965 reg_root
, client_state_path
.c_str(), KEY_QUERY_VALUE
| KEY_WOW64_32KEY
);
966 if (result
== ERROR_SUCCESS
) {
967 result
= client_state
.ReadValue(google_update::kExperimentLabels
,
971 // If the key or value was not present, return the empty string.
972 if (result
== ERROR_FILE_NOT_FOUND
|| result
== ERROR_PATH_NOT_FOUND
) {
973 experiment_labels
->clear();
977 return result
== ERROR_SUCCESS
;