[Android] Added UMA for search by image context menu.
[chromium-blink-merge.git] / chrome / installer / util / google_update_settings.cc
blob6e41637dfa6ec4b66037822b35ed8887b845a787
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"
7 #include <algorithm>
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;
28 namespace {
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;
37 #else
38 GoogleUpdateSettings::UPDATES_DISABLED;
39 #endif
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);
49 return true;
52 bool WriteGoogleUpdateStrKeyInternal(BrowserDistribution* dist,
53 const wchar_t* const name,
54 const std::wstring& value) {
55 DCHECK(dist);
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,
70 bool system_level) {
71 bool result = WriteGoogleUpdateStrKeyInternal(dist, name, value);
72 if (!InstallUtil::IsMultiInstall(dist, system_level))
73 return result;
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);
85 std::wstring value;
86 if (key.ReadValue(name, &value) != ERROR_SUCCESS)
87 return false;
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))
96 return true;
97 return (key.DeleteValue(name) == ERROR_SUCCESS);
100 bool GetChromeChannelInternal(bool system_install,
101 bool add_multi_modifier,
102 string16* channel) {
103 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
104 if (dist->GetChromeChannel(channel)) {
105 return true;
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);
115 return false;
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');
130 return true;
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(
137 const DWORD value,
138 GoogleUpdateSettings::UpdatePolicy* update_policy) {
139 switch (value) {
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);
145 return true;
146 default:
147 LOG(WARNING) << "Unexpected update policy override value: " << value;
149 return false;
152 } // namespace
154 bool GoogleUpdateSettings::IsSystemInstall() {
155 bool system_install = false;
156 base::FilePath module_dir;
157 if (!PathService::Get(base::DIR_MODULE, &module_dir)) {
158 LOG(WARNING)
159 << "Failed to get directory of module; assuming per-user install.";
160 } else {
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);
184 RegKey key;
185 DWORD value = 0;
186 bool have_value = false;
188 // For system-level installs, try ClientStateMedium first.
189 have_value =
190 system_install &&
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.
197 if (!have_value) {
198 have_value =
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,
215 bool consented) {
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();
231 RegKey key;
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;
236 } else {
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,
257 bool consented) {
258 DCHECK(dist);
259 const DWORD eula_accepted = consented ? 1 : 0;
260 std::wstring reg_path = dist->GetStateMediumKey();
261 bool succeeded = true;
262 RegKey key;
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) {
269 succeeded = false;
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) {
285 succeeded = false;
289 return succeeded;
292 int GoogleUpdateSettings::GetLastRunTime() {
293 std::wstring time_s;
294 if (!ReadGoogleUpdateStrKey(google_update::kRegLastRunTimeField, &time_s))
295 return -1;
296 int64 time_i;
297 if (!base::StringToInt64(time_s, &time_i))
298 return -1;
299 base::TimeDelta td =
300 base::Time::NowFromSystemTime() - base::Time::FromInternalValue(time_i);
301 return td.InDays();
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,
328 brand);
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,
348 bool system_level) {
349 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
350 return UpdateDidRunStateForDistribution(dist, did_run, system_level);
353 bool GoogleUpdateSettings::UpdateDidRunStateForDistribution(
354 BrowserDistribution* dist,
355 bool did_run,
356 bool system_level) {
357 return WriteGoogleUpdateStrKeyMultiInstall(dist,
358 google_update::kRegDidRunField,
359 did_run ? L"1" : L"0",
360 system_level);
363 std::wstring GoogleUpdateSettings::GetChromeChannel(bool system_install) {
364 std::wstring channel;
365 GetChromeChannelInternal(system_install, false, &channel);
366 return channel;
369 bool GoogleUpdateSettings::GetChromeChannelAndModifiers(bool system_install,
370 string16* channel) {
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;
381 RegKey key;
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,
394 &channel_info)) {
395 // We have a modified channel_info value to write.
396 // Create the app's ClientState key if it doesn't already exist.
397 if (!key.Valid()) {
398 result = key.Open(reg_root, google_update::kRegPathClientState,
399 KEY_CREATE_SUB_KEY);
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;
405 return;
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: "
426 << value->value();
427 modified = true;
429 } else if (archive_type == installer::INCREMENTAL_ARCHIVE_TYPE) {
430 if (value->SetFullSuffix(true)) {
431 VLOG(1) << "Incremental installer failed; switching to channel: "
432 << value->value();
433 modified = true;
434 } else {
435 VLOG(1) << "Incremental installer failure; already on channel: "
436 << value->value();
438 } else {
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: "
446 << value->value();
447 modified = true;
450 return modified;
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())
460 return 0;
462 HANDLE target_handle = 0;
463 if (!DuplicateHandle(GetCurrentProcess(), reg_key.Handle(),
464 GetCurrentProcess(), &target_handle, KEY_SET_VALUE,
465 TRUE, DUPLICATE_SAME_ACCESS)) {
466 return 0;
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());
488 RegKey policy_key;
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;
495 DWORD value;
496 std::wstring app_update_override;
497 app_update_override.reserve(kPrefixLen + app_guid.size());
498 app_update_override.append(kGoogleUpdateUpdateOverrideValuePrefix,
499 kPrefixLen);
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;
523 string16 cmd_line;
524 RegKey update_key;
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);
531 return cmd_line;
534 Version GoogleUpdateSettings::GetGoogleUpdateVersion(bool system_install) {
535 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
536 string16 version;
537 RegKey key;
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));
547 return Version();
550 base::Time GoogleUpdateSettings::GetGoogleUpdateLastStartedAU(
551 bool system_install) {
552 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
553 RegKey update_key;
555 if (update_key.Open(root_key, google_update::kRegPathGoogleUpdate,
556 KEY_QUERY_VALUE) == ERROR_SUCCESS) {
557 DWORD last_start;
558 if (update_key.ReadValueDW(google_update::kRegLastStartedAUField,
559 &last_start) == ERROR_SUCCESS) {
560 return base::Time::FromTimeT(last_start);
564 return base::Time();
567 base::Time GoogleUpdateSettings::GetGoogleUpdateLastChecked(
568 bool system_install) {
569 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
570 RegKey update_key;
572 if (update_key.Open(root_key, google_update::kRegPathGoogleUpdate,
573 KEY_QUERY_VALUE) == ERROR_SUCCESS) {
574 DWORD last_check;
575 if (update_key.ReadValueDW(google_update::kRegLastCheckedField,
576 &last_check) == ERROR_SUCCESS) {
577 return base::Time::FromTimeT(last_check);
581 return base::Time();
584 bool GoogleUpdateSettings::GetUpdateDetailForApp(bool system_install,
585 const wchar_t* app_guid,
586 ProductData* data) {
587 DCHECK(app_guid);
588 DCHECK(data);
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);
597 RegKey clientstate;
598 if (clientstate.Open(root_key, clientstate_reg_path.c_str(),
599 KEY_QUERY_VALUE) == ERROR_SUCCESS) {
600 string16 version;
601 DWORD dword_value;
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,
635 ProductData* data) {
636 return GetUpdateDetailForApp(system_install,
637 google_update::kGoogleUpdateUpgradeCode,
638 data);
641 bool GoogleUpdateSettings::GetUpdateDetail(bool system_install,
642 ProductData* data) {
643 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
644 return GetUpdateDetailForApp(system_install,
645 dist->GetAppGuid().c_str(),
646 data);
649 bool GoogleUpdateSettings::SetExperimentLabels(
650 bool system_install,
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());
661 RegKey client_state(
662 reg_root, client_state_path.c_str(), KEY_SET_VALUE);
663 if (experiment_labels.empty()) {
664 success = client_state.DeleteValue(google_update::kExperimentLabels)
665 == ERROR_SUCCESS;
666 } else {
667 success = client_state.WriteValue(google_update::kExperimentLabels,
668 experiment_labels.c_str()) == ERROR_SUCCESS;
672 return success;
675 bool GoogleUpdateSettings::ReadExperimentLabels(
676 bool system_install,
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
681 // reading.
682 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
683 if (!dist->ShouldSetExperimentLabels())
684 return false;
686 string16 client_state_path(
687 system_install ? dist->GetStateMediumKey() : dist->GetStateKey());
689 RegKey client_state;
690 LONG result =
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,
694 experiment_labels);
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();
700 return true;
703 return result == ERROR_SUCCESS;