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/path_service.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/thread_restrictions.h"
16 #include "base/time/time.h"
17 #include "base/win/registry.h"
18 #include "base/win/win_util.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/installer/util/browser_distribution.h"
21 #include "chrome/installer/util/channel_info.h"
22 #include "chrome/installer/util/google_update_constants.h"
23 #include "chrome/installer/util/google_update_experiment_util.h"
24 #include "chrome/installer/util/install_util.h"
25 #include "chrome/installer/util/installation_state.h"
26 #include "chrome/installer/util/product.h"
28 using base::win::RegKey
;
29 using installer::InstallationState
;
33 const wchar_t kGoogleUpdatePoliciesKey
[] =
34 L
"SOFTWARE\\Policies\\Google\\Update";
35 const wchar_t kGoogleUpdateUpdatePolicyValue
[] = L
"UpdateDefault";
36 const wchar_t kGoogleUpdateUpdateOverrideValuePrefix
[] = L
"Update";
37 const GoogleUpdateSettings::UpdatePolicy kGoogleUpdateDefaultUpdatePolicy
=
38 #if defined(GOOGLE_CHROME_BUILD)
39 GoogleUpdateSettings::AUTOMATIC_UPDATES
;
41 GoogleUpdateSettings::UPDATES_DISABLED
;
44 bool ReadGoogleUpdateStrKey(const wchar_t* const name
, std::wstring
* value
) {
45 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
46 std::wstring reg_path
= dist
->GetStateKey();
47 RegKey
key(HKEY_CURRENT_USER
, reg_path
.c_str(), KEY_READ
);
48 if (key
.ReadValue(name
, value
) != ERROR_SUCCESS
) {
49 RegKey
hklm_key(HKEY_LOCAL_MACHINE
, reg_path
.c_str(), KEY_READ
);
50 return (hklm_key
.ReadValue(name
, value
) == ERROR_SUCCESS
);
55 // Update a state registry key |name| to be |value| for the given browser
56 // |dist|. If this is a |system_install|, then update the value under
57 // HKLM (istead of HKCU for user-installs) using a group of keys (one
58 // for each OS user) and also include the method to |aggregate| these
59 // values when reporting.
60 bool WriteGoogleUpdateStrKeyInternal(BrowserDistribution
* dist
,
62 const wchar_t* const name
,
63 // presubmit: allow wstring
64 const std::wstring
& value
,
65 const wchar_t* const aggregate
) {
70 // Machine installs require each OS user to write a unique key under a
71 // named key in HKLM as well as an "aggregation" function that describes
72 // how the values of multiple users are to be combined.
73 std::wstring uniquename
; // presubmit: allow wstring
74 if (!base::win::GetUserSidString(&uniquename
)) {
79 // presubmit: allow wstring
80 std::wstring
reg_path(dist
->GetStateMediumKey());
81 reg_path
.append(L
"\\");
82 reg_path
.append(name
);
83 RegKey
key(HKEY_LOCAL_MACHINE
, reg_path
.c_str(), KEY_SET_VALUE
);
84 key
.WriteValue(google_update::kRegAggregateMethod
, aggregate
);
85 return (key
.WriteValue(uniquename
.c_str(), value
.c_str()) == ERROR_SUCCESS
);
87 // User installs are easy: just write the values to HKCU tree.
88 RegKey
key(HKEY_CURRENT_USER
, dist
->GetStateKey().c_str(), KEY_SET_VALUE
);
89 return (key
.WriteValue(name
, value
.c_str()) == ERROR_SUCCESS
);
93 bool WriteGoogleUpdateStrKey(const wchar_t* const name
,
94 const std::wstring
& value
) {
95 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
96 return WriteGoogleUpdateStrKeyInternal(dist
, false, name
, value
, NULL
);
99 bool WriteGoogleUpdateStrKeyMultiInstall(BrowserDistribution
* dist
,
100 const wchar_t* const name
,
101 const std::wstring
& value
,
103 bool result
= WriteGoogleUpdateStrKeyInternal(dist
, false, name
, value
, NULL
);
104 if (!InstallUtil::IsMultiInstall(dist
, system_level
))
106 // It is a multi-install distro. Must write the reg value again.
107 BrowserDistribution
* multi_dist
=
108 BrowserDistribution::GetSpecificDistribution(
109 BrowserDistribution::CHROME_BINARIES
);
111 WriteGoogleUpdateStrKeyInternal(multi_dist
, false, name
, value
, NULL
) &&
115 bool ClearGoogleUpdateStrKey(const wchar_t* const name
) {
116 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
117 std::wstring reg_path
= dist
->GetStateKey();
118 RegKey
key(HKEY_CURRENT_USER
, reg_path
.c_str(), KEY_READ
| KEY_WRITE
);
120 if (key
.ReadValue(name
, &value
) != ERROR_SUCCESS
)
122 return (key
.WriteValue(name
, L
"") == ERROR_SUCCESS
);
125 bool RemoveGoogleUpdateStrKey(const wchar_t* const name
) {
126 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
127 std::wstring reg_path
= dist
->GetStateKey();
128 RegKey
key(HKEY_CURRENT_USER
, reg_path
.c_str(), KEY_READ
| KEY_WRITE
);
129 if (!key
.HasValue(name
))
131 return (key
.DeleteValue(name
) == ERROR_SUCCESS
);
134 bool GetChromeChannelInternal(bool system_install
,
135 bool add_multi_modifier
,
136 base::string16
* channel
) {
137 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
138 if (dist
->GetChromeChannel(channel
)) {
142 HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
143 base::string16 reg_path
= dist
->GetStateKey();
144 RegKey
key(root_key
, reg_path
.c_str(), KEY_READ
);
146 installer::ChannelInfo channel_info
;
147 if (!channel_info
.Initialize(key
)) {
148 channel
->assign(installer::kChromeChannelUnknown
);
152 if (!channel_info
.GetChannelName(channel
)) {
153 channel
->assign(installer::kChromeChannelUnknown
);
156 // Tag the channel name if this is a multi-install.
157 if (add_multi_modifier
&& channel_info
.IsMultiInstall()) {
158 if (!channel
->empty()) {
159 channel
->append(1, L
'-');
161 channel
->append(1, L
'm');
167 // Populates |update_policy| with the UpdatePolicy enum value corresponding to a
168 // DWORD read from the registry and returns true if |value| is within range.
169 // If |value| is out of range, returns false without modifying |update_policy|.
170 bool GetUpdatePolicyFromDword(
172 GoogleUpdateSettings::UpdatePolicy
* update_policy
) {
174 case GoogleUpdateSettings::UPDATES_DISABLED
:
175 case GoogleUpdateSettings::AUTOMATIC_UPDATES
:
176 case GoogleUpdateSettings::MANUAL_UPDATES_ONLY
:
177 case GoogleUpdateSettings::AUTO_UPDATES_ONLY
:
178 *update_policy
= static_cast<GoogleUpdateSettings::UpdatePolicy
>(value
);
181 LOG(WARNING
) << "Unexpected update policy override value: " << value
;
188 bool GoogleUpdateSettings::IsSystemInstall() {
189 bool system_install
= false;
190 base::FilePath module_dir
;
191 if (!PathService::Get(base::DIR_MODULE
, &module_dir
)) {
193 << "Failed to get directory of module; assuming per-user install.";
195 system_install
= !InstallUtil::IsPerUserInstall(module_dir
.value().c_str());
197 return system_install
;
200 bool GoogleUpdateSettings::GetCollectStatsConsent() {
201 return GetCollectStatsConsentAtLevel(IsSystemInstall());
204 // Older versions of Chrome unconditionally read from HKCU\...\ClientState\...
205 // and then HKLM\...\ClientState\.... This means that system-level Chrome
206 // never checked ClientStateMedium (which has priority according to Google
207 // Update) and gave preference to a value in HKCU (which was never checked by
208 // Google Update). From now on, Chrome follows Google Update's policy.
209 bool GoogleUpdateSettings::GetCollectStatsConsentAtLevel(bool system_install
) {
210 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
212 // Consent applies to all products in a multi-install package.
213 if (InstallUtil::IsMultiInstall(dist
, system_install
)) {
214 dist
= BrowserDistribution::GetSpecificDistribution(
215 BrowserDistribution::CHROME_BINARIES
);
220 bool have_value
= false;
222 // For system-level installs, try ClientStateMedium first.
225 key
.Open(HKEY_LOCAL_MACHINE
, dist
->GetStateMediumKey().c_str(),
226 KEY_QUERY_VALUE
) == ERROR_SUCCESS
&&
227 key
.ReadValueDW(google_update::kRegUsageStatsField
,
228 &value
) == ERROR_SUCCESS
;
230 // Otherwise, try ClientState.
233 key
.Open(system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
234 dist
->GetStateKey().c_str(),
235 KEY_QUERY_VALUE
) == ERROR_SUCCESS
&&
236 key
.ReadValueDW(google_update::kRegUsageStatsField
,
237 &value
) == ERROR_SUCCESS
;
240 // Google Update specifically checks that the value is 1, so we do the same.
241 return have_value
&& value
== 1;
244 bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented
) {
245 return SetCollectStatsConsentAtLevel(IsSystemInstall(), consented
);
248 bool GoogleUpdateSettings::SetCollectStatsConsentAtLevel(bool system_install
,
250 // Google Update writes and expects 1 for true, 0 for false.
251 DWORD value
= consented
? 1 : 0;
253 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
255 // Consent applies to all products in a multi-install package.
256 if (InstallUtil::IsMultiInstall(dist
, system_install
)) {
257 dist
= BrowserDistribution::GetSpecificDistribution(
258 BrowserDistribution::CHROME_BINARIES
);
261 // Write to ClientStateMedium for system-level; ClientState otherwise.
262 HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
263 std::wstring reg_path
=
264 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey();
266 LONG result
= key
.Create(root_key
, reg_path
.c_str(), KEY_SET_VALUE
);
267 if (result
!= ERROR_SUCCESS
) {
268 LOG(ERROR
) << "Failed opening key " << reg_path
<< " to set "
269 << google_update::kRegUsageStatsField
<< "; result: " << result
;
271 result
= key
.WriteValue(google_update::kRegUsageStatsField
, value
);
272 LOG_IF(ERROR
, result
!= ERROR_SUCCESS
) << "Failed setting "
273 << google_update::kRegUsageStatsField
<< " in key " << reg_path
274 << "; result: " << result
;
276 return (result
== ERROR_SUCCESS
);
279 bool GoogleUpdateSettings::GetMetricsId(std::string
* metrics_id
) {
280 std::wstring metrics_id_w
;
281 bool rv
= ReadGoogleUpdateStrKey(google_update::kRegMetricsId
, &metrics_id_w
);
282 *metrics_id
= base::WideToUTF8(metrics_id_w
);
286 bool GoogleUpdateSettings::SetMetricsId(const std::string
& metrics_id
) {
287 std::wstring metrics_id_w
= base::UTF8ToWide(metrics_id
);
288 return WriteGoogleUpdateStrKey(google_update::kRegMetricsId
, metrics_id_w
);
291 // EULA consent is only relevant for system-level installs.
292 bool GoogleUpdateSettings::SetEULAConsent(
293 const InstallationState
& machine_state
,
294 BrowserDistribution
* dist
,
297 const DWORD eula_accepted
= consented
? 1 : 0;
298 std::wstring reg_path
= dist
->GetStateMediumKey();
299 bool succeeded
= true;
302 // Write the consent value into the product's ClientStateMedium key.
303 if (key
.Create(HKEY_LOCAL_MACHINE
, reg_path
.c_str(),
304 KEY_SET_VALUE
) != ERROR_SUCCESS
||
305 key
.WriteValue(google_update::kRegEULAAceptedField
,
306 eula_accepted
) != ERROR_SUCCESS
) {
310 // If this is a multi-install, also write it into the binaries' key.
311 // --mutli-install is not provided on the command-line, so deduce it from
312 // the product's state.
313 const installer::ProductState
* product_state
=
314 machine_state
.GetProductState(true, dist
->GetType());
315 if (product_state
!= NULL
&& product_state
->is_multi_install()) {
316 dist
= BrowserDistribution::GetSpecificDistribution(
317 BrowserDistribution::CHROME_BINARIES
);
318 reg_path
= dist
->GetStateMediumKey();
319 if (key
.Create(HKEY_LOCAL_MACHINE
, reg_path
.c_str(),
320 KEY_SET_VALUE
) != ERROR_SUCCESS
||
321 key
.WriteValue(google_update::kRegEULAAceptedField
,
322 eula_accepted
) != ERROR_SUCCESS
) {
330 int GoogleUpdateSettings::GetLastRunTime() {
332 if (!ReadGoogleUpdateStrKey(google_update::kRegLastRunTimeField
, &time_s
))
335 if (!base::StringToInt64(time_s
, &time_i
))
338 base::Time::NowFromSystemTime() - base::Time::FromInternalValue(time_i
);
342 bool GoogleUpdateSettings::SetLastRunTime() {
343 int64 time
= base::Time::NowFromSystemTime().ToInternalValue();
344 return WriteGoogleUpdateStrKey(google_update::kRegLastRunTimeField
,
345 base::Int64ToString16(time
));
348 bool GoogleUpdateSettings::RemoveLastRunTime() {
349 return RemoveGoogleUpdateStrKey(google_update::kRegLastRunTimeField
);
352 bool GoogleUpdateSettings::GetBrowser(std::wstring
* browser
) {
353 return ReadGoogleUpdateStrKey(google_update::kRegBrowserField
, browser
);
356 bool GoogleUpdateSettings::GetLanguage(std::wstring
* language
) {
357 return ReadGoogleUpdateStrKey(google_update::kRegLangField
, language
);
360 bool GoogleUpdateSettings::GetBrand(std::wstring
* brand
) {
361 return ReadGoogleUpdateStrKey(google_update::kRegRLZBrandField
, brand
);
364 bool GoogleUpdateSettings::GetReactivationBrand(std::wstring
* brand
) {
365 return ReadGoogleUpdateStrKey(google_update::kRegRLZReactivationBrandField
,
369 bool GoogleUpdateSettings::GetClient(std::wstring
* client
) {
370 return ReadGoogleUpdateStrKey(google_update::kRegClientField
, client
);
373 bool GoogleUpdateSettings::SetClient(const std::wstring
& client
) {
374 return WriteGoogleUpdateStrKey(google_update::kRegClientField
, client
);
377 bool GoogleUpdateSettings::GetReferral(std::wstring
* referral
) {
378 return ReadGoogleUpdateStrKey(google_update::kRegReferralField
, referral
);
381 bool GoogleUpdateSettings::ClearReferral() {
382 return ClearGoogleUpdateStrKey(google_update::kRegReferralField
);
385 bool GoogleUpdateSettings::UpdateDidRunState(bool did_run
,
387 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
388 return UpdateDidRunStateForDistribution(dist
, did_run
, system_level
);
391 bool GoogleUpdateSettings::UpdateDidRunStateForDistribution(
392 BrowserDistribution
* dist
,
395 return WriteGoogleUpdateStrKeyMultiInstall(dist
,
396 google_update::kRegDidRunField
,
397 did_run
? L
"1" : L
"0",
401 std::wstring
GoogleUpdateSettings::GetChromeChannel(bool system_install
) {
402 std::wstring channel
;
403 GetChromeChannelInternal(system_install
, false, &channel
);
407 bool GoogleUpdateSettings::GetChromeChannelAndModifiers(
409 base::string16
* channel
) {
410 return GetChromeChannelInternal(system_install
, true, channel
);
413 void GoogleUpdateSettings::UpdateInstallStatus(bool system_install
,
414 installer::ArchiveType archive_type
, int install_return_code
,
415 const std::wstring
& product_guid
) {
416 DCHECK(archive_type
!= installer::UNKNOWN_ARCHIVE_TYPE
||
417 install_return_code
!= 0);
418 HKEY reg_root
= (system_install
) ? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
421 installer::ChannelInfo channel_info
;
422 std::wstring
reg_key(google_update::kRegPathClientState
);
423 reg_key
.append(L
"\\");
424 reg_key
.append(product_guid
);
425 LONG result
= key
.Open(reg_root
, reg_key
.c_str(),
426 KEY_QUERY_VALUE
| KEY_SET_VALUE
);
427 if (result
== ERROR_SUCCESS
)
428 channel_info
.Initialize(key
);
429 else if (result
!= ERROR_FILE_NOT_FOUND
)
430 LOG(ERROR
) << "Failed to open " << reg_key
<< "; Error: " << result
;
432 if (UpdateGoogleUpdateApKey(archive_type
, install_return_code
,
434 // We have a modified channel_info value to write.
435 // Create the app's ClientState key if it doesn't already exist.
437 result
= key
.Open(reg_root
, google_update::kRegPathClientState
,
439 if (result
== ERROR_SUCCESS
)
440 result
= key
.CreateKey(product_guid
.c_str(), KEY_SET_VALUE
);
442 if (result
!= ERROR_SUCCESS
) {
443 LOG(ERROR
) << "Failed to create " << reg_key
<< "; Error: " << result
;
447 if (!channel_info
.Write(&key
)) {
448 LOG(ERROR
) << "Failed to write to application's ClientState key "
449 << google_update::kRegApField
<< " = " << channel_info
.value();
454 bool GoogleUpdateSettings::UpdateGoogleUpdateApKey(
455 installer::ArchiveType archive_type
, int install_return_code
,
456 installer::ChannelInfo
* value
) {
457 DCHECK(archive_type
!= installer::UNKNOWN_ARCHIVE_TYPE
||
458 install_return_code
!= 0);
459 bool modified
= false;
461 if (archive_type
== installer::FULL_ARCHIVE_TYPE
|| !install_return_code
) {
462 if (value
->SetFullSuffix(false)) {
463 VLOG(1) << "Removed incremental installer failure key; "
464 "switching to channel: "
468 } else if (archive_type
== installer::INCREMENTAL_ARCHIVE_TYPE
) {
469 if (value
->SetFullSuffix(true)) {
470 VLOG(1) << "Incremental installer failed; switching to channel: "
474 VLOG(1) << "Incremental installer failure; already on channel: "
478 // It's okay if we don't know the archive type. In this case, leave the
479 // "-full" suffix as we found it.
480 DCHECK_EQ(installer::UNKNOWN_ARCHIVE_TYPE
, archive_type
);
483 if (value
->SetMultiFailSuffix(false)) {
484 VLOG(1) << "Removed multi-install failure key; switching to channel: "
492 void GoogleUpdateSettings::UpdateProfileCounts(int profiles_active
,
493 int profiles_signedin
) {
494 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
495 bool system_install
= IsSystemInstall();
496 WriteGoogleUpdateStrKeyInternal(dist
, system_install
,
497 google_update::kRegProfilesActive
,
498 base::Int64ToString16(profiles_active
),
500 WriteGoogleUpdateStrKeyInternal(dist
, system_install
,
501 google_update::kRegProfilesSignedIn
,
502 base::Int64ToString16(profiles_signedin
),
506 int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() {
507 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
508 std::wstring reg_path
= dist
->GetStateKey();
510 // Minimum access needed is to be able to write to this key.
511 RegKey
reg_key(HKEY_LOCAL_MACHINE
, reg_path
.c_str(), KEY_SET_VALUE
);
512 if (!reg_key
.Valid())
515 HANDLE target_handle
= 0;
516 if (!DuplicateHandle(GetCurrentProcess(), reg_key
.Handle(),
517 GetCurrentProcess(), &target_handle
, KEY_SET_VALUE
,
518 TRUE
, DUPLICATE_SAME_ACCESS
)) {
521 return reinterpret_cast<int>(target_handle
);
524 bool GoogleUpdateSettings::WriteGoogleUpdateSystemClientKey(
525 int handle
, const std::wstring
& key
, const std::wstring
& value
) {
526 HKEY reg_key
= reinterpret_cast<HKEY
>(reinterpret_cast<void*>(handle
));
527 DWORD size
= static_cast<DWORD
>(value
.size()) * sizeof(wchar_t);
528 LSTATUS status
= RegSetValueEx(reg_key
, key
.c_str(), 0, REG_SZ
,
529 reinterpret_cast<const BYTE
*>(value
.c_str()), size
);
530 return status
== ERROR_SUCCESS
;
533 GoogleUpdateSettings::UpdatePolicy
GoogleUpdateSettings::GetAppUpdatePolicy(
534 const std::wstring
& app_guid
,
535 bool* is_overridden
) {
536 bool found_override
= false;
537 UpdatePolicy update_policy
= kGoogleUpdateDefaultUpdatePolicy
;
539 #if defined(GOOGLE_CHROME_BUILD)
540 DCHECK(!app_guid
.empty());
543 // Google Update Group Policy settings are always in HKLM.
544 if (policy_key
.Open(HKEY_LOCAL_MACHINE
, kGoogleUpdatePoliciesKey
,
545 KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
546 static const size_t kPrefixLen
=
547 arraysize(kGoogleUpdateUpdateOverrideValuePrefix
) - 1;
549 std::wstring app_update_override
;
550 app_update_override
.reserve(kPrefixLen
+ app_guid
.size());
551 app_update_override
.append(kGoogleUpdateUpdateOverrideValuePrefix
,
553 app_update_override
.append(app_guid
);
554 // First try to read and comprehend the app-specific override.
555 found_override
= (policy_key
.ReadValueDW(app_update_override
.c_str(),
556 &value
) == ERROR_SUCCESS
&&
557 GetUpdatePolicyFromDword(value
, &update_policy
));
559 // Failing that, try to read and comprehend the default override.
560 if (!found_override
&&
561 policy_key
.ReadValueDW(kGoogleUpdateUpdatePolicyValue
,
562 &value
) == ERROR_SUCCESS
) {
563 GetUpdatePolicyFromDword(value
, &update_policy
);
566 #endif // defined(GOOGLE_CHROME_BUILD)
568 if (is_overridden
!= NULL
)
569 *is_overridden
= found_override
;
571 return update_policy
;
574 base::string16
GoogleUpdateSettings::GetUninstallCommandLine(
575 bool system_install
) {
576 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
577 base::string16 cmd_line
;
580 if (update_key
.Open(root_key
, google_update::kRegPathGoogleUpdate
,
581 KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
582 update_key
.ReadValue(google_update::kRegUninstallCmdLine
, &cmd_line
);
588 Version
GoogleUpdateSettings::GetGoogleUpdateVersion(bool system_install
) {
589 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
590 base::string16 version
;
593 if (key
.Open(root_key
,
594 google_update::kRegPathGoogleUpdate
,
595 KEY_QUERY_VALUE
) == ERROR_SUCCESS
&&
596 key
.ReadValue(google_update::kRegGoogleUpdateVersion
,
597 &version
) == ERROR_SUCCESS
) {
598 return Version(base::UTF16ToUTF8(version
));
604 base::Time
GoogleUpdateSettings::GetGoogleUpdateLastStartedAU(
605 bool system_install
) {
606 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
609 if (update_key
.Open(root_key
, google_update::kRegPathGoogleUpdate
,
610 KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
612 if (update_key
.ReadValueDW(google_update::kRegLastStartedAUField
,
613 &last_start
) == ERROR_SUCCESS
) {
614 return base::Time::FromTimeT(last_start
);
621 base::Time
GoogleUpdateSettings::GetGoogleUpdateLastChecked(
622 bool system_install
) {
623 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
626 if (update_key
.Open(root_key
, google_update::kRegPathGoogleUpdate
,
627 KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
629 if (update_key
.ReadValueDW(google_update::kRegLastCheckedField
,
630 &last_check
) == ERROR_SUCCESS
) {
631 return base::Time::FromTimeT(last_check
);
638 bool GoogleUpdateSettings::GetUpdateDetailForApp(bool system_install
,
639 const wchar_t* app_guid
,
644 bool product_found
= false;
646 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
647 base::string16
clientstate_reg_path(google_update::kRegPathClientState
);
648 clientstate_reg_path
.append(L
"\\");
649 clientstate_reg_path
.append(app_guid
);
652 if (clientstate
.Open(root_key
, clientstate_reg_path
.c_str(),
653 KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
654 base::string16 version
;
656 if ((clientstate
.ReadValueDW(google_update::kRegLastCheckSuccessField
,
657 &dword_value
) == ERROR_SUCCESS
) &&
658 (clientstate
.ReadValue(google_update::kRegVersionField
,
659 &version
) == ERROR_SUCCESS
)) {
660 product_found
= true;
661 data
->version
= WideToASCII(version
);
662 data
->last_success
= base::Time::FromTimeT(dword_value
);
663 data
->last_result
= 0;
664 data
->last_error_code
= 0;
665 data
->last_extra_code
= 0;
667 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerResultField
,
668 &dword_value
) == ERROR_SUCCESS
) {
669 // Google Update convention is that if an installer writes an result
670 // code that is invalid, it is clamped to an exit code result.
671 const DWORD kMaxValidInstallResult
= 4; // INSTALLER_RESULT_EXIT_CODE
672 data
->last_result
= std::min(dword_value
, kMaxValidInstallResult
);
674 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerErrorField
,
675 &dword_value
) == ERROR_SUCCESS
) {
676 data
->last_error_code
= dword_value
;
678 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerExtraField
,
679 &dword_value
) == ERROR_SUCCESS
) {
680 data
->last_extra_code
= dword_value
;
685 return product_found
;
688 bool GoogleUpdateSettings::GetUpdateDetailForGoogleUpdate(bool system_install
,
690 return GetUpdateDetailForApp(system_install
,
691 google_update::kGoogleUpdateUpgradeCode
,
695 bool GoogleUpdateSettings::GetUpdateDetail(bool system_install
,
697 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
698 return GetUpdateDetailForApp(system_install
,
699 dist
->GetAppGuid().c_str(),
703 bool GoogleUpdateSettings::SetExperimentLabels(
705 const base::string16
& experiment_labels
) {
706 HKEY reg_root
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
708 // Use the browser distribution and install level to write to the correct
709 // client state/app guid key.
710 bool success
= false;
711 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
712 if (dist
->ShouldSetExperimentLabels()) {
713 base::string16
client_state_path(
714 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey());
716 reg_root
, client_state_path
.c_str(), KEY_SET_VALUE
);
717 if (experiment_labels
.empty()) {
718 success
= client_state
.DeleteValue(google_update::kExperimentLabels
)
721 success
= client_state
.WriteValue(google_update::kExperimentLabels
,
722 experiment_labels
.c_str()) == ERROR_SUCCESS
;
729 bool GoogleUpdateSettings::ReadExperimentLabels(
731 base::string16
* experiment_labels
) {
732 HKEY reg_root
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
734 // If this distribution does not set the experiment labels, don't bother
736 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
737 if (!dist
->ShouldSetExperimentLabels())
740 base::string16
client_state_path(
741 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey());
745 client_state
.Open(reg_root
, client_state_path
.c_str(), KEY_QUERY_VALUE
);
746 if (result
== ERROR_SUCCESS
) {
747 result
= client_state
.ReadValue(google_update::kExperimentLabels
,
751 // If the key or value was not present, return the empty string.
752 if (result
== ERROR_FILE_NOT_FOUND
|| result
== ERROR_PATH_NOT_FOUND
) {
753 experiment_labels
->clear();
757 return result
== ERROR_SUCCESS
;