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/path_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/threading/thread_restrictions.h"
15 #include "base/time/time.h"
16 #include "base/win/registry.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/installer/util/browser_distribution.h"
19 #include "chrome/installer/util/channel_info.h"
20 #include "chrome/installer/util/google_update_constants.h"
21 #include "chrome/installer/util/install_util.h"
22 #include "chrome/installer/util/installation_state.h"
23 #include "chrome/installer/util/product.h"
25 using base::win::RegKey
;
26 using installer::InstallationState
;
30 const wchar_t kGoogleUpdatePoliciesKey
[] =
31 L
"SOFTWARE\\Policies\\Google\\Update";
32 const wchar_t kGoogleUpdateUpdatePolicyValue
[] = L
"UpdateDefault";
33 const wchar_t kGoogleUpdateUpdateOverrideValuePrefix
[] = L
"Update";
34 const GoogleUpdateSettings::UpdatePolicy kGoogleUpdateDefaultUpdatePolicy
=
35 #if defined(GOOGLE_CHROME_BUILD)
36 GoogleUpdateSettings::AUTOMATIC_UPDATES
;
38 GoogleUpdateSettings::UPDATES_DISABLED
;
41 bool ReadGoogleUpdateStrKey(const wchar_t* const name
, std::wstring
* value
) {
42 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
43 std::wstring reg_path
= dist
->GetStateKey();
44 RegKey
key(HKEY_CURRENT_USER
, reg_path
.c_str(), KEY_READ
);
45 if (key
.ReadValue(name
, value
) != ERROR_SUCCESS
) {
46 RegKey
hklm_key(HKEY_LOCAL_MACHINE
, reg_path
.c_str(), KEY_READ
);
47 return (hklm_key
.ReadValue(name
, value
) == ERROR_SUCCESS
);
52 bool WriteGoogleUpdateStrKeyInternal(BrowserDistribution
* dist
,
53 const wchar_t* const name
,
54 const std::wstring
& value
) {
56 std::wstring
reg_path(dist
->GetStateKey());
57 RegKey
key(HKEY_CURRENT_USER
, reg_path
.c_str(), KEY_SET_VALUE
);
58 return (key
.WriteValue(name
, value
.c_str()) == ERROR_SUCCESS
);
61 bool WriteGoogleUpdateStrKey(const wchar_t* const name
,
62 const std::wstring
& value
) {
63 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
64 return WriteGoogleUpdateStrKeyInternal(dist
, name
, value
);
67 bool WriteGoogleUpdateStrKeyMultiInstall(BrowserDistribution
* dist
,
68 const wchar_t* const name
,
69 const std::wstring
& value
,
71 bool result
= WriteGoogleUpdateStrKeyInternal(dist
, name
, value
);
72 if (!InstallUtil::IsMultiInstall(dist
, system_level
))
74 // It is a multi-install distro. Must write the reg value again.
75 BrowserDistribution
* multi_dist
=
76 BrowserDistribution::GetSpecificDistribution(
77 BrowserDistribution::CHROME_BINARIES
);
78 return WriteGoogleUpdateStrKeyInternal(multi_dist
, name
, value
) && result
;
81 bool ClearGoogleUpdateStrKey(const wchar_t* const name
) {
82 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
83 std::wstring reg_path
= dist
->GetStateKey();
84 RegKey
key(HKEY_CURRENT_USER
, reg_path
.c_str(), KEY_READ
| KEY_WRITE
);
86 if (key
.ReadValue(name
, &value
) != ERROR_SUCCESS
)
88 return (key
.WriteValue(name
, L
"") == ERROR_SUCCESS
);
91 bool RemoveGoogleUpdateStrKey(const wchar_t* const name
) {
92 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
93 std::wstring reg_path
= dist
->GetStateKey();
94 RegKey
key(HKEY_CURRENT_USER
, reg_path
.c_str(), KEY_READ
| KEY_WRITE
);
95 if (!key
.HasValue(name
))
97 return (key
.DeleteValue(name
) == ERROR_SUCCESS
);
100 bool GetChromeChannelInternal(bool system_install
,
101 bool add_multi_modifier
,
103 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
104 if (dist
->GetChromeChannel(channel
)) {
108 HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
109 string16 reg_path
= dist
->GetStateKey();
110 RegKey
key(root_key
, reg_path
.c_str(), KEY_READ
);
112 installer::ChannelInfo channel_info
;
113 if (!channel_info
.Initialize(key
)) {
114 channel
->assign(installer::kChromeChannelUnknown
);
118 if (!channel_info
.GetChannelName(channel
)) {
119 channel
->assign(installer::kChromeChannelUnknown
);
122 // Tag the channel name if this is a multi-install.
123 if (add_multi_modifier
&& channel_info
.IsMultiInstall()) {
124 if (!channel
->empty()) {
125 channel
->append(1, L
'-');
127 channel
->append(1, L
'm');
133 // Populates |update_policy| with the UpdatePolicy enum value corresponding to a
134 // DWORD read from the registry and returns true if |value| is within range.
135 // If |value| is out of range, returns false without modifying |update_policy|.
136 bool GetUpdatePolicyFromDword(
138 GoogleUpdateSettings::UpdatePolicy
* update_policy
) {
140 case GoogleUpdateSettings::UPDATES_DISABLED
:
141 case GoogleUpdateSettings::AUTOMATIC_UPDATES
:
142 case GoogleUpdateSettings::MANUAL_UPDATES_ONLY
:
143 case GoogleUpdateSettings::AUTO_UPDATES_ONLY
:
144 *update_policy
= static_cast<GoogleUpdateSettings::UpdatePolicy
>(value
);
147 LOG(WARNING
) << "Unexpected update policy override value: " << value
;
154 bool GoogleUpdateSettings::IsSystemInstall() {
155 bool system_install
= false;
156 base::FilePath module_dir
;
157 if (!PathService::Get(base::DIR_MODULE
, &module_dir
)) {
159 << "Failed to get directory of module; assuming per-user install.";
161 system_install
= !InstallUtil::IsPerUserInstall(module_dir
.value().c_str());
163 return system_install
;
166 bool GoogleUpdateSettings::GetCollectStatsConsent() {
167 return GetCollectStatsConsentAtLevel(IsSystemInstall());
170 // Older versions of Chrome unconditionally read from HKCU\...\ClientState\...
171 // and then HKLM\...\ClientState\.... This means that system-level Chrome
172 // never checked ClientStateMedium (which has priority according to Google
173 // Update) and gave preference to a value in HKCU (which was never checked by
174 // Google Update). From now on, Chrome follows Google Update's policy.
175 bool GoogleUpdateSettings::GetCollectStatsConsentAtLevel(bool system_install
) {
176 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
178 // Consent applies to all products in a multi-install package.
179 if (InstallUtil::IsMultiInstall(dist
, system_install
)) {
180 dist
= BrowserDistribution::GetSpecificDistribution(
181 BrowserDistribution::CHROME_BINARIES
);
186 bool have_value
= false;
188 // For system-level installs, try ClientStateMedium first.
191 key
.Open(HKEY_LOCAL_MACHINE
, dist
->GetStateMediumKey().c_str(),
192 KEY_QUERY_VALUE
) == ERROR_SUCCESS
&&
193 key
.ReadValueDW(google_update::kRegUsageStatsField
,
194 &value
) == ERROR_SUCCESS
;
196 // Otherwise, try ClientState.
199 key
.Open(system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
200 dist
->GetStateKey().c_str(),
201 KEY_QUERY_VALUE
) == ERROR_SUCCESS
&&
202 key
.ReadValueDW(google_update::kRegUsageStatsField
,
203 &value
) == ERROR_SUCCESS
;
206 // Google Update specifically checks that the value is 1, so we do the same.
207 return have_value
&& value
== 1;
210 bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented
) {
211 return SetCollectStatsConsentAtLevel(IsSystemInstall(), consented
);
214 bool GoogleUpdateSettings::SetCollectStatsConsentAtLevel(bool system_install
,
216 // Google Update writes and expects 1 for true, 0 for false.
217 DWORD value
= consented
? 1 : 0;
219 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
221 // Consent applies to all products in a multi-install package.
222 if (InstallUtil::IsMultiInstall(dist
, system_install
)) {
223 dist
= BrowserDistribution::GetSpecificDistribution(
224 BrowserDistribution::CHROME_BINARIES
);
227 // Write to ClientStateMedium for system-level; ClientState otherwise.
228 HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
229 std::wstring reg_path
=
230 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey();
232 LONG result
= key
.Create(root_key
, reg_path
.c_str(), KEY_SET_VALUE
);
233 if (result
!= ERROR_SUCCESS
) {
234 LOG(ERROR
) << "Failed opening key " << reg_path
<< " to set "
235 << google_update::kRegUsageStatsField
<< "; result: " << result
;
237 result
= key
.WriteValue(google_update::kRegUsageStatsField
, value
);
238 LOG_IF(ERROR
, result
!= ERROR_SUCCESS
) << "Failed setting "
239 << google_update::kRegUsageStatsField
<< " in key " << reg_path
240 << "; result: " << result
;
242 return (result
== ERROR_SUCCESS
);
245 bool GoogleUpdateSettings::GetMetricsId(std::wstring
* metrics_id
) {
246 return ReadGoogleUpdateStrKey(google_update::kRegMetricsId
, metrics_id
);
249 bool GoogleUpdateSettings::SetMetricsId(const std::wstring
& metrics_id
) {
250 return WriteGoogleUpdateStrKey(google_update::kRegMetricsId
, metrics_id
);
253 // EULA consent is only relevant for system-level installs.
254 bool GoogleUpdateSettings::SetEULAConsent(
255 const InstallationState
& machine_state
,
256 BrowserDistribution
* dist
,
259 const DWORD eula_accepted
= consented
? 1 : 0;
260 std::wstring reg_path
= dist
->GetStateMediumKey();
261 bool succeeded
= true;
264 // Write the consent value into the product's ClientStateMedium key.
265 if (key
.Create(HKEY_LOCAL_MACHINE
, reg_path
.c_str(),
266 KEY_SET_VALUE
) != ERROR_SUCCESS
||
267 key
.WriteValue(google_update::kRegEULAAceptedField
,
268 eula_accepted
) != ERROR_SUCCESS
) {
272 // If this is a multi-install, also write it into the binaries' key.
273 // --mutli-install is not provided on the command-line, so deduce it from
274 // the product's state.
275 const installer::ProductState
* product_state
=
276 machine_state
.GetProductState(true, dist
->GetType());
277 if (product_state
!= NULL
&& product_state
->is_multi_install()) {
278 dist
= BrowserDistribution::GetSpecificDistribution(
279 BrowserDistribution::CHROME_BINARIES
);
280 reg_path
= dist
->GetStateMediumKey();
281 if (key
.Create(HKEY_LOCAL_MACHINE
, reg_path
.c_str(),
282 KEY_SET_VALUE
) != ERROR_SUCCESS
||
283 key
.WriteValue(google_update::kRegEULAAceptedField
,
284 eula_accepted
) != ERROR_SUCCESS
) {
292 int GoogleUpdateSettings::GetLastRunTime() {
294 if (!ReadGoogleUpdateStrKey(google_update::kRegLastRunTimeField
, &time_s
))
297 if (!base::StringToInt64(time_s
, &time_i
))
300 base::Time::NowFromSystemTime() - base::Time::FromInternalValue(time_i
);
304 bool GoogleUpdateSettings::SetLastRunTime() {
305 int64 time
= base::Time::NowFromSystemTime().ToInternalValue();
306 return WriteGoogleUpdateStrKey(google_update::kRegLastRunTimeField
,
307 base::Int64ToString16(time
));
310 bool GoogleUpdateSettings::RemoveLastRunTime() {
311 return RemoveGoogleUpdateStrKey(google_update::kRegLastRunTimeField
);
314 bool GoogleUpdateSettings::GetBrowser(std::wstring
* browser
) {
315 return ReadGoogleUpdateStrKey(google_update::kRegBrowserField
, browser
);
318 bool GoogleUpdateSettings::GetLanguage(std::wstring
* language
) {
319 return ReadGoogleUpdateStrKey(google_update::kRegLangField
, language
);
322 bool GoogleUpdateSettings::GetBrand(std::wstring
* brand
) {
323 return ReadGoogleUpdateStrKey(google_update::kRegRLZBrandField
, brand
);
326 bool GoogleUpdateSettings::GetReactivationBrand(std::wstring
* brand
) {
327 return ReadGoogleUpdateStrKey(google_update::kRegRLZReactivationBrandField
,
331 bool GoogleUpdateSettings::GetClient(std::wstring
* client
) {
332 return ReadGoogleUpdateStrKey(google_update::kRegClientField
, client
);
335 bool GoogleUpdateSettings::SetClient(const std::wstring
& client
) {
336 return WriteGoogleUpdateStrKey(google_update::kRegClientField
, client
);
339 bool GoogleUpdateSettings::GetReferral(std::wstring
* referral
) {
340 return ReadGoogleUpdateStrKey(google_update::kRegReferralField
, referral
);
343 bool GoogleUpdateSettings::ClearReferral() {
344 return ClearGoogleUpdateStrKey(google_update::kRegReferralField
);
347 bool GoogleUpdateSettings::UpdateDidRunState(bool did_run
,
349 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
350 return UpdateDidRunStateForDistribution(dist
, did_run
, system_level
);
353 bool GoogleUpdateSettings::UpdateDidRunStateForDistribution(
354 BrowserDistribution
* dist
,
357 return WriteGoogleUpdateStrKeyMultiInstall(dist
,
358 google_update::kRegDidRunField
,
359 did_run
? L
"1" : L
"0",
363 std::wstring
GoogleUpdateSettings::GetChromeChannel(bool system_install
) {
364 std::wstring channel
;
365 GetChromeChannelInternal(system_install
, false, &channel
);
369 bool GoogleUpdateSettings::GetChromeChannelAndModifiers(bool system_install
,
371 return GetChromeChannelInternal(system_install
, true, channel
);
374 void GoogleUpdateSettings::UpdateInstallStatus(bool system_install
,
375 installer::ArchiveType archive_type
, int install_return_code
,
376 const std::wstring
& product_guid
) {
377 DCHECK(archive_type
!= installer::UNKNOWN_ARCHIVE_TYPE
||
378 install_return_code
!= 0);
379 HKEY reg_root
= (system_install
) ? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
382 installer::ChannelInfo channel_info
;
383 std::wstring
reg_key(google_update::kRegPathClientState
);
384 reg_key
.append(L
"\\");
385 reg_key
.append(product_guid
);
386 LONG result
= key
.Open(reg_root
, reg_key
.c_str(),
387 KEY_QUERY_VALUE
| KEY_SET_VALUE
);
388 if (result
== ERROR_SUCCESS
)
389 channel_info
.Initialize(key
);
390 else if (result
!= ERROR_FILE_NOT_FOUND
)
391 LOG(ERROR
) << "Failed to open " << reg_key
<< "; Error: " << result
;
393 if (UpdateGoogleUpdateApKey(archive_type
, install_return_code
,
395 // We have a modified channel_info value to write.
396 // Create the app's ClientState key if it doesn't already exist.
398 result
= key
.Open(reg_root
, google_update::kRegPathClientState
,
400 if (result
== ERROR_SUCCESS
)
401 result
= key
.CreateKey(product_guid
.c_str(), KEY_SET_VALUE
);
403 if (result
!= ERROR_SUCCESS
) {
404 LOG(ERROR
) << "Failed to create " << reg_key
<< "; Error: " << result
;
408 if (!channel_info
.Write(&key
)) {
409 LOG(ERROR
) << "Failed to write to application's ClientState key "
410 << google_update::kRegApField
<< " = " << channel_info
.value();
415 bool GoogleUpdateSettings::UpdateGoogleUpdateApKey(
416 installer::ArchiveType archive_type
, int install_return_code
,
417 installer::ChannelInfo
* value
) {
418 DCHECK(archive_type
!= installer::UNKNOWN_ARCHIVE_TYPE
||
419 install_return_code
!= 0);
420 bool modified
= false;
422 if (archive_type
== installer::FULL_ARCHIVE_TYPE
|| !install_return_code
) {
423 if (value
->SetFullSuffix(false)) {
424 VLOG(1) << "Removed incremental installer failure key; "
425 "switching to channel: "
429 } else if (archive_type
== installer::INCREMENTAL_ARCHIVE_TYPE
) {
430 if (value
->SetFullSuffix(true)) {
431 VLOG(1) << "Incremental installer failed; switching to channel: "
435 VLOG(1) << "Incremental installer failure; already on channel: "
439 // It's okay if we don't know the archive type. In this case, leave the
440 // "-full" suffix as we found it.
441 DCHECK_EQ(installer::UNKNOWN_ARCHIVE_TYPE
, archive_type
);
444 if (value
->SetMultiFailSuffix(false)) {
445 VLOG(1) << "Removed multi-install failure key; switching to channel: "
453 int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() {
454 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
455 std::wstring reg_path
= dist
->GetStateKey();
457 // Minimum access needed is to be able to write to this key.
458 RegKey
reg_key(HKEY_LOCAL_MACHINE
, reg_path
.c_str(), KEY_SET_VALUE
);
459 if (!reg_key
.Valid())
462 HANDLE target_handle
= 0;
463 if (!DuplicateHandle(GetCurrentProcess(), reg_key
.Handle(),
464 GetCurrentProcess(), &target_handle
, KEY_SET_VALUE
,
465 TRUE
, DUPLICATE_SAME_ACCESS
)) {
468 return reinterpret_cast<int>(target_handle
);
471 bool GoogleUpdateSettings::WriteGoogleUpdateSystemClientKey(
472 int handle
, const std::wstring
& key
, const std::wstring
& value
) {
473 HKEY reg_key
= reinterpret_cast<HKEY
>(reinterpret_cast<void*>(handle
));
474 DWORD size
= static_cast<DWORD
>(value
.size()) * sizeof(wchar_t);
475 LSTATUS status
= RegSetValueEx(reg_key
, key
.c_str(), 0, REG_SZ
,
476 reinterpret_cast<const BYTE
*>(value
.c_str()), size
);
477 return status
== ERROR_SUCCESS
;
480 GoogleUpdateSettings::UpdatePolicy
GoogleUpdateSettings::GetAppUpdatePolicy(
481 const std::wstring
& app_guid
,
482 bool* is_overridden
) {
483 bool found_override
= false;
484 UpdatePolicy update_policy
= kGoogleUpdateDefaultUpdatePolicy
;
486 #if defined(GOOGLE_CHROME_BUILD)
487 DCHECK(!app_guid
.empty());
490 // Google Update Group Policy settings are always in HKLM.
491 if (policy_key
.Open(HKEY_LOCAL_MACHINE
, kGoogleUpdatePoliciesKey
,
492 KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
493 static const size_t kPrefixLen
=
494 arraysize(kGoogleUpdateUpdateOverrideValuePrefix
) - 1;
496 std::wstring app_update_override
;
497 app_update_override
.reserve(kPrefixLen
+ app_guid
.size());
498 app_update_override
.append(kGoogleUpdateUpdateOverrideValuePrefix
,
500 app_update_override
.append(app_guid
);
501 // First try to read and comprehend the app-specific override.
502 found_override
= (policy_key
.ReadValueDW(app_update_override
.c_str(),
503 &value
) == ERROR_SUCCESS
&&
504 GetUpdatePolicyFromDword(value
, &update_policy
));
506 // Failing that, try to read and comprehend the default override.
507 if (!found_override
&&
508 policy_key
.ReadValueDW(kGoogleUpdateUpdatePolicyValue
,
509 &value
) == ERROR_SUCCESS
) {
510 GetUpdatePolicyFromDword(value
, &update_policy
);
513 #endif // defined(GOOGLE_CHROME_BUILD)
515 if (is_overridden
!= NULL
)
516 *is_overridden
= found_override
;
518 return update_policy
;
521 string16
GoogleUpdateSettings::GetUninstallCommandLine(bool system_install
) {
522 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
526 if (update_key
.Open(root_key
, google_update::kRegPathGoogleUpdate
,
527 KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
528 update_key
.ReadValue(google_update::kRegUninstallCmdLine
, &cmd_line
);
534 Version
GoogleUpdateSettings::GetGoogleUpdateVersion(bool system_install
) {
535 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
539 if (key
.Open(root_key
,
540 google_update::kRegPathGoogleUpdate
,
541 KEY_QUERY_VALUE
) == ERROR_SUCCESS
&&
542 key
.ReadValue(google_update::kRegGoogleUpdateVersion
,
543 &version
) == ERROR_SUCCESS
) {
544 return Version(UTF16ToUTF8(version
));
550 base::Time
GoogleUpdateSettings::GetGoogleUpdateLastStartedAU(
551 bool system_install
) {
552 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
555 if (update_key
.Open(root_key
, google_update::kRegPathGoogleUpdate
,
556 KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
558 if (update_key
.ReadValueDW(google_update::kRegLastStartedAUField
,
559 &last_start
) == ERROR_SUCCESS
) {
560 return base::Time::FromTimeT(last_start
);
567 base::Time
GoogleUpdateSettings::GetGoogleUpdateLastChecked(
568 bool system_install
) {
569 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
572 if (update_key
.Open(root_key
, google_update::kRegPathGoogleUpdate
,
573 KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
575 if (update_key
.ReadValueDW(google_update::kRegLastCheckedField
,
576 &last_check
) == ERROR_SUCCESS
) {
577 return base::Time::FromTimeT(last_check
);
584 bool GoogleUpdateSettings::GetUpdateDetailForApp(bool system_install
,
585 const wchar_t* app_guid
,
590 bool product_found
= false;
592 const HKEY root_key
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
593 string16
clientstate_reg_path(google_update::kRegPathClientState
);
594 clientstate_reg_path
.append(L
"\\");
595 clientstate_reg_path
.append(app_guid
);
598 if (clientstate
.Open(root_key
, clientstate_reg_path
.c_str(),
599 KEY_QUERY_VALUE
) == ERROR_SUCCESS
) {
602 if ((clientstate
.ReadValueDW(google_update::kRegLastCheckSuccessField
,
603 &dword_value
) == ERROR_SUCCESS
) &&
604 (clientstate
.ReadValue(google_update::kRegVersionField
,
605 &version
) == ERROR_SUCCESS
)) {
606 product_found
= true;
607 data
->version
= WideToASCII(version
);
608 data
->last_success
= base::Time::FromTimeT(dword_value
);
609 data
->last_result
= 0;
610 data
->last_error_code
= 0;
611 data
->last_extra_code
= 0;
613 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerResultField
,
614 &dword_value
) == ERROR_SUCCESS
) {
615 // Google Update convention is that if an installer writes an result
616 // code that is invalid, it is clamped to an exit code result.
617 const DWORD kMaxValidInstallResult
= 4; // INSTALLER_RESULT_EXIT_CODE
618 data
->last_result
= std::min(dword_value
, kMaxValidInstallResult
);
620 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerErrorField
,
621 &dword_value
) == ERROR_SUCCESS
) {
622 data
->last_error_code
= dword_value
;
624 if (clientstate
.ReadValueDW(google_update::kRegLastInstallerExtraField
,
625 &dword_value
) == ERROR_SUCCESS
) {
626 data
->last_extra_code
= dword_value
;
631 return product_found
;
634 bool GoogleUpdateSettings::GetUpdateDetailForGoogleUpdate(bool system_install
,
636 return GetUpdateDetailForApp(system_install
,
637 google_update::kGoogleUpdateUpgradeCode
,
641 bool GoogleUpdateSettings::GetUpdateDetail(bool system_install
,
643 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
644 return GetUpdateDetailForApp(system_install
,
645 dist
->GetAppGuid().c_str(),
649 bool GoogleUpdateSettings::SetExperimentLabels(
651 const string16
& experiment_labels
) {
652 HKEY reg_root
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
654 // Use the browser distribution and install level to write to the correct
655 // client state/app guid key.
656 bool success
= false;
657 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
658 if (dist
->ShouldSetExperimentLabels()) {
659 string16
client_state_path(
660 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey());
662 reg_root
, client_state_path
.c_str(), KEY_SET_VALUE
);
663 if (experiment_labels
.empty()) {
664 success
= client_state
.DeleteValue(google_update::kExperimentLabels
)
667 success
= client_state
.WriteValue(google_update::kExperimentLabels
,
668 experiment_labels
.c_str()) == ERROR_SUCCESS
;
675 bool GoogleUpdateSettings::ReadExperimentLabels(
677 string16
* experiment_labels
) {
678 HKEY reg_root
= system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
680 // If this distribution does not set the experiment labels, don't bother
682 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
683 if (!dist
->ShouldSetExperimentLabels())
686 string16
client_state_path(
687 system_install
? dist
->GetStateMediumKey() : dist
->GetStateKey());
691 client_state
.Open(reg_root
, client_state_path
.c_str(), KEY_QUERY_VALUE
);
692 if (result
== ERROR_SUCCESS
) {
693 result
= client_state
.ReadValue(google_update::kExperimentLabels
,
697 // If the key or value was not present, return the empty string.
698 if (result
== ERROR_FILE_NOT_FOUND
|| result
== ERROR_PATH_NOT_FOUND
) {
699 experiment_labels
->clear();
703 return result
== ERROR_SUCCESS
;