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"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/metrics/histogram.h"
13 #include "base/path_service.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/threading/thread_restrictions.h"
18 #include "base/time/time.h"
19 #include "base/win/registry.h"
20 #include "base/win/win_util.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/installer/util/app_registration_data.h"
23 #include "chrome/installer/util/browser_distribution.h"
24 #include "chrome/installer/util/channel_info.h"
25 #include "chrome/installer/util/google_update_constants.h"
26 #include "chrome/installer/util/google_update_experiment_util.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 // Updates a registry key |name| to be |value| for the given |app_reg_data|.
68 // If this is a |system_install|, then update the value under HKLM (istead of
69 // HKCU for user-installs) using a group of keys (one for each OS user) and also
70 // include the method to |aggregate| these values when reporting.
71 bool WriteGoogleUpdateStrKeyInternal(const AppRegistrationData
& app_reg_data
,
73 const wchar_t* const name
,
74 const base::string16
& value
,
75 const wchar_t* const aggregate
) {
76 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
);
93 return (key
.WriteValue(uniquename
.c_str(), value
.c_str()) == ERROR_SUCCESS
);
95 // User installs are easy: just write the values to HKCU tree.
96 RegKey
key(HKEY_CURRENT_USER
, app_reg_data
.GetStateKey().c_str(), kAccess
);
97 return (key
.WriteValue(name
, value
.c_str()) == ERROR_SUCCESS
);
101 bool WriteGoogleUpdateStrKey(const wchar_t* const name
,
102 const base::string16
& value
) {
103 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
104 return WriteGoogleUpdateStrKeyInternal(
105 dist
->GetAppRegistrationData(), false, name
, value
, NULL
);
108 bool ClearGoogleUpdateStrKey(const wchar_t* const name
) {
109 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
110 base::string16 reg_path
= dist
->GetStateKey();
111 RegKey
key(HKEY_CURRENT_USER
,
113 KEY_READ
| KEY_WRITE
| KEY_WOW64_32KEY
);
114 base::string16 value
;
115 if (key
.ReadValue(name
, &value
) != ERROR_SUCCESS
)
117 return (key
.WriteValue(name
, L
"") == ERROR_SUCCESS
);
120 bool RemoveGoogleUpdateStrKey(const wchar_t* const name
) {
121 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
122 base::string16 reg_path
= dist
->GetStateKey();
123 RegKey
key(HKEY_CURRENT_USER
,
125 KEY_READ
| KEY_WRITE
| KEY_WOW64_32KEY
);
126 if (!key
.HasValue(name
))
128 return (key
.DeleteValue(name
) == ERROR_SUCCESS
);
131 bool GetChromeChannelInternal(bool system_install
,
132 bool add_multi_modifier
,
133 base::string16
* channel
) {
134 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
136 // Shortcut in case this distribution knows what channel it is (canary).
137 if (dist
->GetChromeChannel(channel
))
140 // Determine whether or not chrome is multi-install. If so, updates are
141 // delivered under the binaries' app guid, so that's where the relevant
143 installer::ProductState state
;
144 installer::ChannelInfo channel_info
;
145 ignore_result(state
.Initialize(system_install
, dist
));
146 if (!state
.is_multi_install()) {
147 // Use the channel info that was just read for this single-install chrome.
148 channel_info
= state
.channel();
150 // Read the channel info from the binaries' state key.
151 HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
152 dist
= BrowserDistribution::GetSpecificDistribution(
153 BrowserDistribution::CHROME_BINARIES
);
154 RegKey
key(root_key
, dist
->GetStateKey().c_str(),
155 KEY_READ
| KEY_WOW64_32KEY
);
157 if (!channel_info
.Initialize(key
)) {
158 channel
->assign(installer::kChromeChannelUnknown
);
163 if (!channel_info
.GetChannelName(channel
))
164 channel
->assign(installer::kChromeChannelUnknown
);
166 // Tag the channel name if this is a multi-install.
167 if (add_multi_modifier
&& state
.is_multi_install()) {
168 if (!channel
->empty())
169 channel
->push_back(L
'-');
170 channel
->push_back(L
'm');
176 // Populates |update_policy| with the UpdatePolicy enum value corresponding to a
177 // DWORD read from the registry and returns true if |value| is within range.
178 // If |value| is out of range, returns false without modifying |update_policy|.
179 bool GetUpdatePolicyFromDword(
181 GoogleUpdateSettings::UpdatePolicy
* update_policy
) {
183 case GoogleUpdateSettings::UPDATES_DISABLED
:
184 case GoogleUpdateSettings::AUTOMATIC_UPDATES
:
185 case GoogleUpdateSettings::MANUAL_UPDATES_ONLY
:
186 case GoogleUpdateSettings::AUTO_UPDATES_ONLY
:
187 *update_policy
= static_cast<GoogleUpdateSettings::UpdatePolicy
>(value
);
190 LOG(WARNING
) << "Unexpected update policy override value: " << value
;
195 // Convenience routine: GoogleUpdateSettings::UpdateDidRunStateForApp()
196 // specialized for Chrome Binaries.
197 bool UpdateDidRunStateForBinaries(bool did_run
) {
198 BrowserDistribution
* dist
= BrowserDistribution::GetSpecificDistribution(
199 BrowserDistribution::CHROME_BINARIES
);
200 return GoogleUpdateSettings::UpdateDidRunStateForApp(
201 dist
->GetAppRegistrationData(), did_run
);
206 bool GoogleUpdateSettings::IsSystemInstall() {
207 bool system_install
= false;
208 base::FilePath module_dir
;
209 if (!PathService::Get(base::DIR_MODULE
, &module_dir
)) {
211 << "Failed to get directory of module; assuming per-user install.";
213 system_install
= !InstallUtil::IsPerUserInstall(module_dir
.value().c_str());
215 return system_install
;
218 bool GoogleUpdateSettings::GetCollectStatsConsent() {
219 return GetCollectStatsConsentAtLevel(IsSystemInstall());
222 // Older versions of Chrome unconditionally read from HKCU\...\ClientState\...
223 // and then HKLM\...\ClientState\.... This means that system-level Chrome
224 // never checked ClientStateMedium (which has priority according to Google
225 // Update) and gave preference to a value in HKCU (which was never checked by
226 // Google Update). From now on, Chrome follows Google Update's policy.
227 bool GoogleUpdateSettings::GetCollectStatsConsentAtLevel(bool system_install
) {
228 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
230 // Consent applies to all products in a multi-install package.
231 if (InstallUtil::IsMultiInstall(dist
, system_install
)) {
232 dist
= BrowserDistribution::GetSpecificDistribution(
233 BrowserDistribution::CHROME_BINARIES
);
238 bool have_value
= false;
239 const REGSAM kAccess
= KEY_QUERY_VALUE
| KEY_WOW64_32KEY
;
241 // For system-level installs, try ClientStateMedium first.
244 key
.Open(HKEY_LOCAL_MACHINE
, dist
->GetStateMediumKey().c_str(),
245 kAccess
) == ERROR_SUCCESS
&&
246 key
.ReadValueDW(google_update::kRegUsageStatsField
,
247 &value
) == ERROR_SUCCESS
;
249 // Otherwise, try ClientState.
252 key
.Open(system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
253 dist
->GetStateKey().c_str(),
254 kAccess
) == ERROR_SUCCESS
&&
255 key
.ReadValueDW(google_update::kRegUsageStatsField
,
256 &value
) == ERROR_SUCCESS
;
259 // Google Update specifically checks that the value is 1, so we do the same.
260 return have_value
&& value
== 1;
263 bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented
) {
264 return SetCollectStatsConsentAtLevel(IsSystemInstall(), consented
);
267 bool GoogleUpdateSettings::SetCollectStatsConsentAtLevel(bool system_install
,
269 // Google Update writes and expects 1 for true, 0 for false.
270 DWORD value
= consented
? 1 : 0;
272 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
274 // Consent applies to all products in a multi-install package.
275 if (InstallUtil::IsMultiInstall(dist
, system_install
)) {
276 dist
= BrowserDistribution::GetSpecificDistribution(
277 BrowserDistribution::CHROME_BINARIES
);
280 // Write to ClientStateMedium for system-level; ClientState otherwise.
281 HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
282 base::string16 reg_path
=
283 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey();
285 LONG result
= key
.Create(
286 root_key
, reg_path
.c_str(), KEY_SET_VALUE
| KEY_WOW64_32KEY
);
287 if (result
!= ERROR_SUCCESS
) {
288 LOG(ERROR
) << "Failed opening key " << reg_path
<< " to set "
289 << google_update::kRegUsageStatsField
<< "; result: " << result
;
291 result
= key
.WriteValue(google_update::kRegUsageStatsField
, value
);
292 LOG_IF(ERROR
, result
!= ERROR_SUCCESS
) << "Failed setting "
293 << google_update::kRegUsageStatsField
<< " in key " << reg_path
294 << "; result: " << result
;
296 return (result
== ERROR_SUCCESS
);
299 scoped_ptr
<metrics::ClientInfo
> GoogleUpdateSettings::LoadMetricsClientInfo() {
300 base::string16 client_id_16
;
301 if (!ReadGoogleUpdateStrKey(google_update::kRegMetricsId
, &client_id_16
) ||
302 client_id_16
.empty()) {
303 return scoped_ptr
<metrics::ClientInfo
>();
306 scoped_ptr
<metrics::ClientInfo
> client_info(new metrics::ClientInfo
);
307 client_info
->client_id
= base::UTF16ToUTF8(client_id_16
);
309 base::string16 installation_date_str
;
310 if (ReadGoogleUpdateStrKey(google_update::kRegMetricsIdInstallDate
,
311 &installation_date_str
)) {
312 base::StringToInt64(installation_date_str
, &client_info
->installation_date
);
315 base::string16 reporting_enbaled_date_date_str
;
316 if (ReadGoogleUpdateStrKey(google_update::kRegMetricsIdEnabledDate
,
317 &reporting_enbaled_date_date_str
)) {
318 base::StringToInt64(reporting_enbaled_date_date_str
,
319 &client_info
->reporting_enabled_date
);
322 return client_info
.Pass();
325 void GoogleUpdateSettings::StoreMetricsClientInfo(
326 const metrics::ClientInfo
& client_info
) {
327 // Attempt a best-effort at backing |client_info| in the registry (but don't
328 // handle/report failures).
329 WriteGoogleUpdateStrKey(google_update::kRegMetricsId
,
330 base::UTF8ToUTF16(client_info
.client_id
));
331 WriteGoogleUpdateStrKey(google_update::kRegMetricsIdInstallDate
,
332 base::Int64ToString16(client_info
.installation_date
));
333 WriteGoogleUpdateStrKey(
334 google_update::kRegMetricsIdEnabledDate
,
335 base::Int64ToString16(client_info
.reporting_enabled_date
));
338 // EULA consent is only relevant for system-level installs.
339 bool GoogleUpdateSettings::SetEULAConsent(
340 const InstallationState
& machine_state
,
341 BrowserDistribution
* dist
,
344 const DWORD eula_accepted
= consented
? 1 : 0;
345 const REGSAM kAccess
= KEY_SET_VALUE
| KEY_WOW64_32KEY
;
346 base::string16 reg_path
= dist
->GetStateMediumKey();
347 bool succeeded
= true;
350 // Write the consent value into the product's ClientStateMedium key.
351 if (key
.Create(HKEY_LOCAL_MACHINE
, reg_path
.c_str(),
352 kAccess
) != ERROR_SUCCESS
||
353 key
.WriteValue(google_update::kRegEULAAceptedField
,
354 eula_accepted
) != ERROR_SUCCESS
) {
358 // If this is a multi-install, also write it into the binaries' key.
359 // --mutli-install is not provided on the command-line, so deduce it from
360 // the product's state.
361 const installer::ProductState
* product_state
=
362 machine_state
.GetProductState(true, dist
->GetType());
363 if (product_state
!= NULL
&& product_state
->is_multi_install()) {
364 dist
= BrowserDistribution::GetSpecificDistribution(
365 BrowserDistribution::CHROME_BINARIES
);
366 reg_path
= dist
->GetStateMediumKey();
367 if (key
.Create(HKEY_LOCAL_MACHINE
, reg_path
.c_str(),
368 kAccess
) != ERROR_SUCCESS
||
369 key
.WriteValue(google_update::kRegEULAAceptedField
,
370 eula_accepted
) != ERROR_SUCCESS
) {
378 int GoogleUpdateSettings::GetLastRunTime() {
379 base::string16 time_s
;
380 if (!ReadGoogleUpdateStrKey(google_update::kRegLastRunTimeField
, &time_s
))
383 if (!base::StringToInt64(time_s
, &time_i
))
386 base::Time::NowFromSystemTime() - base::Time::FromInternalValue(time_i
);
390 bool GoogleUpdateSettings::SetLastRunTime() {
391 int64 time
= base::Time::NowFromSystemTime().ToInternalValue();
392 return WriteGoogleUpdateStrKey(google_update::kRegLastRunTimeField
,
393 base::Int64ToString16(time
));
396 bool GoogleUpdateSettings::RemoveLastRunTime() {
397 return RemoveGoogleUpdateStrKey(google_update::kRegLastRunTimeField
);
400 bool GoogleUpdateSettings::GetBrowser(base::string16
* browser
) {
401 return ReadGoogleUpdateStrKey(google_update::kRegBrowserField
, browser
);
404 bool GoogleUpdateSettings::GetLanguage(base::string16
* language
) {
405 return ReadGoogleUpdateStrKey(google_update::kRegLangField
, language
);
408 bool GoogleUpdateSettings::GetBrand(base::string16
* brand
) {
409 return ReadGoogleUpdateStrKey(google_update::kRegRLZBrandField
, brand
);
412 bool GoogleUpdateSettings::GetReactivationBrand(base::string16
* brand
) {
413 return ReadGoogleUpdateStrKey(google_update::kRegRLZReactivationBrandField
,
417 bool GoogleUpdateSettings::GetClient(base::string16
* client
) {
418 return ReadGoogleUpdateStrKey(google_update::kRegClientField
, client
);
421 bool GoogleUpdateSettings::SetClient(const base::string16
& client
) {
422 return WriteGoogleUpdateStrKey(google_update::kRegClientField
, client
);
425 bool GoogleUpdateSettings::GetReferral(base::string16
* referral
) {
426 return ReadGoogleUpdateStrKey(google_update::kRegReferralField
, referral
);
429 bool GoogleUpdateSettings::ClearReferral() {
430 return ClearGoogleUpdateStrKey(google_update::kRegReferralField
);
433 bool GoogleUpdateSettings::UpdateDidRunStateForApp(
434 const AppRegistrationData
& app_reg_data
,
436 return WriteGoogleUpdateStrKeyInternal(app_reg_data
,
437 false, // user level.
438 google_update::kRegDidRunField
,
439 did_run
? L
"1" : L
"0",
443 bool GoogleUpdateSettings::UpdateDidRunState(bool did_run
, bool system_level
) {
444 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
445 bool result
= UpdateDidRunStateForApp(dist
->GetAppRegistrationData(),
447 // Update state for binaries, even if the previous call was unsuccessful.
448 if (InstallUtil::IsMultiInstall(dist
, system_level
))
449 result
= UpdateDidRunStateForBinaries(did_run
) && result
;
453 base::string16
GoogleUpdateSettings::GetChromeChannel(bool system_install
) {
454 base::string16 channel
;
455 GetChromeChannelInternal(system_install
, false, &channel
);
459 bool GoogleUpdateSettings::GetChromeChannelAndModifiers(
461 base::string16
* channel
) {
462 return GetChromeChannelInternal(system_install
, true, channel
);
465 void GoogleUpdateSettings::UpdateInstallStatus(bool system_install
,
466 installer::ArchiveType archive_type
, int install_return_code
,
467 const base::string16
& product_guid
) {
468 DCHECK(archive_type
!= installer::UNKNOWN_ARCHIVE_TYPE
||
469 install_return_code
!= 0);
470 HKEY reg_root
= (system_install
) ? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
473 installer::ChannelInfo channel_info
;
474 base::string16
reg_key(google_update::kRegPathClientState
);
475 reg_key
.append(L
"\\");
476 reg_key
.append(product_guid
);
477 LONG result
= key
.Open(reg_root
,
479 KEY_QUERY_VALUE
| KEY_SET_VALUE
| KEY_WOW64_32KEY
);
480 if (result
== ERROR_SUCCESS
)
481 channel_info
.Initialize(key
);
482 else if (result
!= ERROR_FILE_NOT_FOUND
)
483 LOG(ERROR
) << "Failed to open " << reg_key
<< "; Error: " << result
;
485 if (UpdateGoogleUpdateApKey(archive_type
, install_return_code
,
487 // We have a modified channel_info value to write.
488 // Create the app's ClientState key if it doesn't already exist.
490 result
= key
.Open(reg_root
,
491 google_update::kRegPathClientState
,
492 KEY_CREATE_SUB_KEY
| KEY_WOW64_32KEY
);
493 if (result
== ERROR_SUCCESS
)
494 result
= key
.CreateKey(product_guid
.c_str(),
495 KEY_SET_VALUE
| KEY_WOW64_32KEY
);
497 if (result
!= ERROR_SUCCESS
) {
498 LOG(ERROR
) << "Failed to create " << reg_key
<< "; Error: " << result
;
502 if (!channel_info
.Write(&key
)) {
503 LOG(ERROR
) << "Failed to write to application's ClientState key "
504 << google_update::kRegApField
<< " = " << channel_info
.value();
509 bool GoogleUpdateSettings::UpdateGoogleUpdateApKey(
510 installer::ArchiveType archive_type
, int install_return_code
,
511 installer::ChannelInfo
* value
) {
512 DCHECK(archive_type
!= installer::UNKNOWN_ARCHIVE_TYPE
||
513 install_return_code
!= 0);
514 bool modified
= false;
516 if (archive_type
== installer::FULL_ARCHIVE_TYPE
|| !install_return_code
) {
517 if (value
->SetFullSuffix(false)) {
518 VLOG(1) << "Removed incremental installer failure key; "
519 "switching to channel: "
523 } else if (archive_type
== installer::INCREMENTAL_ARCHIVE_TYPE
) {
524 if (value
->SetFullSuffix(true)) {
525 VLOG(1) << "Incremental installer failed; switching to channel: "
529 VLOG(1) << "Incremental installer failure; already on channel: "
533 // It's okay if we don't know the archive type. In this case, leave the
534 // "-full" suffix as we found it.
535 DCHECK_EQ(installer::UNKNOWN_ARCHIVE_TYPE
, archive_type
);
538 if (value
->SetMultiFailSuffix(false)) {
539 VLOG(1) << "Removed multi-install failure key; switching to channel: "
547 void GoogleUpdateSettings::UpdateProfileCounts(int profiles_active
,
548 int profiles_signedin
) {
549 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
550 bool system_install
= IsSystemInstall();
551 WriteGoogleUpdateStrKeyInternal(dist
->GetAppRegistrationData(),
553 google_update::kRegProfilesActive
,
554 base::Int64ToString16(profiles_active
),
556 WriteGoogleUpdateStrKeyInternal(dist
->GetAppRegistrationData(),
558 google_update::kRegProfilesSignedIn
,
559 base::Int64ToString16(profiles_signedin
),
563 int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() {
564 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
565 base::string16 reg_path
= dist
->GetStateKey();
567 // Minimum access needed is to be able to write to this key.
569 HKEY_LOCAL_MACHINE
, reg_path
.c_str(), KEY_SET_VALUE
| KEY_WOW64_32KEY
);
570 if (!reg_key
.Valid())
573 HANDLE target_handle
= 0;
574 if (!DuplicateHandle(GetCurrentProcess(), reg_key
.Handle(),
575 GetCurrentProcess(), &target_handle
, KEY_SET_VALUE
,
576 TRUE
, DUPLICATE_SAME_ACCESS
)) {
579 return reinterpret_cast<int>(target_handle
);
582 bool GoogleUpdateSettings::WriteGoogleUpdateSystemClientKey(
583 int handle
, const base::string16
& key
, const base::string16
& value
) {
584 HKEY reg_key
= reinterpret_cast<HKEY
>(reinterpret_cast<void*>(handle
));
585 DWORD size
= static_cast<DWORD
>(value
.size()) * sizeof(wchar_t);
586 LSTATUS status
= RegSetValueEx(reg_key
, key
.c_str(), 0, REG_SZ
,
587 reinterpret_cast<const BYTE
*>(value
.c_str()), size
);
588 return status
== ERROR_SUCCESS
;
591 GoogleUpdateSettings::UpdatePolicy
GoogleUpdateSettings::GetAppUpdatePolicy(
592 const base::string16
& app_guid
,
593 bool* is_overridden
) {
594 bool found_override
= false;
595 UpdatePolicy update_policy
= kDefaultUpdatePolicy
;
597 #if defined(GOOGLE_CHROME_BUILD)
598 DCHECK(!app_guid
.empty());
601 // Google Update Group Policy settings are always in HKLM.
602 // TODO(wfh): Check if policies should go into Wow6432Node or not.
603 if (policy_key
.Open(HKEY_LOCAL_MACHINE
, kPoliciesKey
, KEY_QUERY_VALUE
) ==
606 base::string16
app_update_override(kUpdateOverrideValuePrefix
);
607 app_update_override
.append(app_guid
);
608 // First try to read and comprehend the app-specific override.
609 found_override
= (policy_key
.ReadValueDW(app_update_override
.c_str(),
610 &value
) == ERROR_SUCCESS
&&
611 GetUpdatePolicyFromDword(value
, &update_policy
));
613 // Failing that, try to read and comprehend the default override.
614 if (!found_override
&&
615 policy_key
.ReadValueDW(kUpdatePolicyValue
, &value
) == ERROR_SUCCESS
) {
616 GetUpdatePolicyFromDword(value
, &update_policy
);
619 #endif // defined(GOOGLE_CHROME_BUILD)
621 if (is_overridden
!= NULL
)
622 *is_overridden
= found_override
;
624 return update_policy
;
628 bool GoogleUpdateSettings::AreAutoupdatesEnabled(
629 const base::string16
& app_guid
) {
630 // Check the auto-update check period override. If it is 0 or exceeds the
631 // maximum timeout, then for all intents and purposes auto updates are
635 if (policy_key
.Open(HKEY_LOCAL_MACHINE
, kPoliciesKey
,
636 KEY_QUERY_VALUE
) == ERROR_SUCCESS
&&
637 policy_key
.ReadValueDW(kCheckPeriodOverrideMinutes
,
638 &value
) == ERROR_SUCCESS
&&
639 (value
== 0 || value
> kCheckPeriodOverrideMinutesMax
)) {
643 UpdatePolicy policy
= GetAppUpdatePolicy(app_guid
, NULL
);
644 return (policy
== AUTOMATIC_UPDATES
|| policy
== AUTO_UPDATES_ONLY
);
648 bool GoogleUpdateSettings::ReenableAutoupdatesForApp(
649 const base::string16
& app_guid
) {
650 #if defined(GOOGLE_CHROME_BUILD)
651 int needs_reset_count
= 0;
652 int did_reset_count
= 0;
654 UpdatePolicy update_policy
= kDefaultUpdatePolicy
;
656 if (policy_key
.Open(HKEY_LOCAL_MACHINE
, kPoliciesKey
,
657 KEY_SET_VALUE
| KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
658 // First check the app-specific override value and reset that if needed.
659 // Note that this intentionally sets the override to AUTOMATIC_UPDATES
660 // even if it was previously AUTO_UPDATES_ONLY. The thinking is that
661 // AUTOMATIC_UPDATES is marginally more likely to let a user update and this
662 // code is only called when a stuck user asks for updates.
663 base::string16
app_update_override(kUpdateOverrideValuePrefix
);
664 app_update_override
.append(app_guid
);
666 bool has_app_update_override
=
667 policy_key
.ReadValueDW(app_update_override
.c_str(),
668 &value
) == ERROR_SUCCESS
;
669 if (has_app_update_override
&&
670 (!GetUpdatePolicyFromDword(value
, &update_policy
) ||
671 update_policy
!= GoogleUpdateSettings::AUTOMATIC_UPDATES
)) {
673 if (policy_key
.WriteValue(
674 app_update_override
.c_str(),
675 static_cast<DWORD
>(GoogleUpdateSettings::AUTOMATIC_UPDATES
)) ==
681 // If there was no app-specific override policy see if there's a global
682 // policy preventing updates and delete it if so.
683 if (!has_app_update_override
&&
684 policy_key
.ReadValueDW(kUpdatePolicyValue
, &value
) == ERROR_SUCCESS
&&
685 (!GetUpdatePolicyFromDword(value
, &update_policy
) ||
686 update_policy
!= GoogleUpdateSettings::AUTOMATIC_UPDATES
)) {
688 if (policy_key
.DeleteValue(kUpdatePolicyValue
) == ERROR_SUCCESS
)
692 // Check the auto-update check period override. If it is 0 or exceeds
693 // the maximum timeout, delete the override value.
694 if (policy_key
.ReadValueDW(kCheckPeriodOverrideMinutes
,
695 &value
) == ERROR_SUCCESS
&&
696 (value
== 0 || value
> kCheckPeriodOverrideMinutesMax
)) {
698 if (policy_key
.DeleteValue(kCheckPeriodOverrideMinutes
) == ERROR_SUCCESS
)
702 // Return whether the number of successful resets is the same as the
703 // number of things that appeared to need resetting.
704 return (needs_reset_count
== did_reset_count
);
706 // For some reason we couldn't open the policy key with the desired
707 // permissions to make changes (the most likely reason is that there is no
708 // policy set). Simply return whether or not we think updates are enabled.
709 return AreAutoupdatesEnabled(app_guid
);
713 // Non Google Chrome isn't going to autoupdate.
717 void GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms() {
718 const bool is_multi_install
= InstallUtil::IsMultiInstall(
719 BrowserDistribution::GetDistribution(), IsSystemInstall());
720 const base::string16 app_guid
=
721 BrowserDistribution::GetSpecificDistribution(
722 is_multi_install
? BrowserDistribution::CHROME_BINARIES
:
723 BrowserDistribution::CHROME_BROWSER
)->GetAppGuid();
725 bool is_overridden
= false;
726 const UpdatePolicy update_policy
= GetAppUpdatePolicy(app_guid
,
728 UMA_HISTOGRAM_BOOLEAN("GoogleUpdate.UpdatePolicyIsOverridden", is_overridden
);
729 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.EffectivePolicy", update_policy
,
730 UPDATE_POLICIES_COUNT
);
733 base::string16
GoogleUpdateSettings::GetUninstallCommandLine(
734 bool system_install
) {
735 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
736 base::string16 cmd_line
;
739 if (update_key
.Open(root_key
, google_update::kRegPathGoogleUpdate
,
740 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
) == ERROR_SUCCESS
) {
741 update_key
.ReadValue(google_update::kRegUninstallCmdLine
, &cmd_line
);
747 Version
GoogleUpdateSettings::GetGoogleUpdateVersion(bool system_install
) {
748 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
749 base::string16 version
;
752 if (key
.Open(root_key
,
753 google_update::kRegPathGoogleUpdate
,
754 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
) == ERROR_SUCCESS
&&
755 key
.ReadValue(google_update::kRegGoogleUpdateVersion
, &version
) ==
757 return Version(base::UTF16ToUTF8(version
));
763 base::Time
GoogleUpdateSettings::GetGoogleUpdateLastStartedAU(
764 bool system_install
) {
765 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
768 if (update_key
.Open(root_key
,
769 google_update::kRegPathGoogleUpdate
,
770 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
) == ERROR_SUCCESS
) {
772 if (update_key
.ReadValueDW(google_update::kRegLastStartedAUField
,
773 &last_start
) == ERROR_SUCCESS
) {
774 return base::Time::FromTimeT(last_start
);
781 base::Time
GoogleUpdateSettings::GetGoogleUpdateLastChecked(
782 bool system_install
) {
783 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
786 if (update_key
.Open(root_key
,
787 google_update::kRegPathGoogleUpdate
,
788 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
) == ERROR_SUCCESS
) {
790 if (update_key
.ReadValueDW(google_update::kRegLastCheckedField
,
791 &last_check
) == ERROR_SUCCESS
) {
792 return base::Time::FromTimeT(last_check
);
799 bool GoogleUpdateSettings::GetUpdateDetailForApp(bool system_install
,
800 const wchar_t* app_guid
,
805 bool product_found
= false;
807 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
808 base::string16
clientstate_reg_path(google_update::kRegPathClientState
);
809 clientstate_reg_path
.append(L
"\\");
810 clientstate_reg_path
.append(app_guid
);
813 if (clientstate
.Open(root_key
,
814 clientstate_reg_path
.c_str(),
815 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
) == ERROR_SUCCESS
) {
816 base::string16 version
;
818 if ((clientstate
.ReadValueDW(google_update::kRegLastCheckSuccessField
,
819 &dword_value
) == ERROR_SUCCESS
) &&
820 (clientstate
.ReadValue(google_update::kRegVersionField
,
821 &version
) == ERROR_SUCCESS
)) {
822 product_found
= true;
823 data
->version
= base::UTF16ToASCII(version
);
824 data
->last_success
= base::Time::FromTimeT(dword_value
);
825 data
->last_result
= 0;
826 data
->last_error_code
= 0;
827 data
->last_extra_code
= 0;
829 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerResultField
,
830 &dword_value
) == ERROR_SUCCESS
) {
831 // Google Update convention is that if an installer writes an result
832 // code that is invalid, it is clamped to an exit code result.
833 const DWORD kMaxValidInstallResult
= 4; // INSTALLER_RESULT_EXIT_CODE
834 data
->last_result
= std::min(dword_value
, kMaxValidInstallResult
);
836 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerErrorField
,
837 &dword_value
) == ERROR_SUCCESS
) {
838 data
->last_error_code
= dword_value
;
840 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerExtraField
,
841 &dword_value
) == ERROR_SUCCESS
) {
842 data
->last_extra_code
= dword_value
;
847 return product_found
;
850 bool GoogleUpdateSettings::GetUpdateDetailForGoogleUpdate(bool system_install
,
852 return GetUpdateDetailForApp(system_install
,
853 google_update::kGoogleUpdateUpgradeCode
,
857 bool GoogleUpdateSettings::GetUpdateDetail(bool system_install
,
859 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
860 return GetUpdateDetailForApp(system_install
,
861 dist
->GetAppGuid().c_str(),
865 bool GoogleUpdateSettings::SetExperimentLabels(
867 const base::string16
& experiment_labels
) {
868 HKEY reg_root
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
870 // Use the browser distribution and install level to write to the correct
871 // client state/app guid key.
872 bool success
= false;
873 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
874 if (dist
->ShouldSetExperimentLabels()) {
875 base::string16
client_state_path(
876 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey());
878 reg_root
, client_state_path
.c_str(), KEY_SET_VALUE
| KEY_WOW64_32KEY
);
879 if (experiment_labels
.empty()) {
880 success
= client_state
.DeleteValue(google_update::kExperimentLabels
)
883 success
= client_state
.WriteValue(google_update::kExperimentLabels
,
884 experiment_labels
.c_str()) == ERROR_SUCCESS
;
891 bool GoogleUpdateSettings::ReadExperimentLabels(
893 base::string16
* experiment_labels
) {
894 HKEY reg_root
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
896 // If this distribution does not set the experiment labels, don't bother
898 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
899 if (!dist
->ShouldSetExperimentLabels())
902 base::string16
client_state_path(
903 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey());
906 LONG result
= client_state
.Open(
907 reg_root
, client_state_path
.c_str(), KEY_QUERY_VALUE
| KEY_WOW64_32KEY
);
908 if (result
== ERROR_SUCCESS
) {
909 result
= client_state
.ReadValue(google_update::kExperimentLabels
,
913 // If the key or value was not present, return the empty string.
914 if (result
== ERROR_FILE_NOT_FOUND
|| result
== ERROR_PATH_NOT_FOUND
) {
915 experiment_labels
->clear();
919 return result
== ERROR_SUCCESS
;