google_update_settings.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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. 4 5#include "chrome/installer/util/google_update_settings.h" 6 7#include <algorithm> 8#include <string> 9 10#include "base/command_line.h" 11#include "base/files/file_path.h" 12#include "base/logging.h" 13#include "base/metrics/histogram.h" 14#include "base/path_service.h" 15#include "base/strings/string_number_conversions.h" 16#include "base/strings/string_util.h" 17#include "base/strings/utf_string_conversions.h" 18#include "base/threading/thread_restrictions.h" 19#include "base/time/time.h" 20#include "base/win/registry.h" 21#include "base/win/win_util.h" 22#include "chrome/common/chrome_switches.h" 23#include "chrome/installer/util/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" 30 31using base::win::RegKey; 32using installer::InstallationState; 33 34const wchar_t GoogleUpdateSettings::kPoliciesKey[] = 35 L"SOFTWARE\\Policies\\Google\\Update"; 36const wchar_t GoogleUpdateSettings::kUpdatePolicyValue[] = L"UpdateDefault"; 37const wchar_t GoogleUpdateSettings::kUpdateOverrideValuePrefix[] = L"Update"; 38const wchar_t GoogleUpdateSettings::kCheckPeriodOverrideMinutes[] = 39 L"AutoUpdateCheckPeriodMinutes"; 40 41// Don't allow update periods longer than six weeks. 42const int GoogleUpdateSettings::kCheckPeriodOverrideMinutesMax = 43 60 * 24 * 7 * 6; 44 45const GoogleUpdateSettings::UpdatePolicy 46GoogleUpdateSettings::kDefaultUpdatePolicy = 47#if defined(GOOGLE_CHROME_BUILD) 48 GoogleUpdateSettings::AUTOMATIC_UPDATES; 49#else 50 GoogleUpdateSettings::UPDATES_DISABLED; 51#endif 52 53namespace { 54 55bool ReadGoogleUpdateStrKey(const wchar_t* const name, std::wstring* value) { 56 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 57 std::wstring reg_path = dist->GetStateKey(); 58 RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ); 59 if (key.ReadValue(name, value) != ERROR_SUCCESS) { 60 RegKey hklm_key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ); 61 return (hklm_key.ReadValue(name, value) == ERROR_SUCCESS); 62 } 63 return true; 64} 65 66// Update a state registry key |name| to be |value| for the given browser 67// |dist|. If this is a |system_install|, then update the value under 68// HKLM (istead of HKCU for user-installs) using a group of keys (one 69// for each OS user) and also include the method to |aggregate| these 70// values when reporting. 71bool WriteGoogleUpdateStrKeyInternal(BrowserDistribution* dist, 72 bool system_install, 73 const wchar_t* const name, 74 // presubmit: allow wstring 75 const std::wstring& value, 76 const wchar_t* const aggregate) { 77 DCHECK(dist); 78 79 if (system_install) { 80 DCHECK(aggregate); 81 // Machine installs require each OS user to write a unique key under a 82 // named key in HKLM as well as an "aggregation" function that describes 83 // how the values of multiple users are to be combined. 84 std::wstring uniquename; // presubmit: allow wstring 85 if (!base::win::GetUserSidString(&uniquename)) { 86 NOTREACHED(); 87 return false; 88 } 89 90 // presubmit: allow wstring 91 std::wstring reg_path(dist->GetStateMediumKey()); 92 reg_path.append(L"\\"); 93 reg_path.append(name); 94 RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_SET_VALUE); 95 key.WriteValue(google_update::kRegAggregateMethod, aggregate); 96 return (key.WriteValue(uniquename.c_str(), value.c_str()) == ERROR_SUCCESS); 97 } else { 98 // User installs are easy: just write the values to HKCU tree. 99 RegKey key(HKEY_CURRENT_USER, dist->GetStateKey().c_str(), KEY_SET_VALUE); 100 return (key.WriteValue(name, value.c_str()) == ERROR_SUCCESS); 101 } 102} 103 104bool WriteGoogleUpdateStrKey(const wchar_t* const name, 105 const std::wstring& value) { 106 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 107 return WriteGoogleUpdateStrKeyInternal(dist, false, name, value, NULL); 108} 109 110bool WriteGoogleUpdateStrKeyMultiInstall(BrowserDistribution* dist, 111 const wchar_t* const name, 112 const std::wstring& value, 113 bool system_level) { 114 bool result = WriteGoogleUpdateStrKeyInternal(dist, false, name, value, NULL); 115 if (!InstallUtil::IsMultiInstall(dist, system_level)) 116 return result; 117 // It is a multi-install distro. Must write the reg value again. 118 BrowserDistribution* multi_dist = 119 BrowserDistribution::GetSpecificDistribution( 120 BrowserDistribution::CHROME_BINARIES); 121 return 122 WriteGoogleUpdateStrKeyInternal(multi_dist, false, name, value, NULL) && 123 result; 124} 125 126bool ClearGoogleUpdateStrKey(const wchar_t* const name) { 127 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 128 std::wstring reg_path = dist->GetStateKey(); 129 RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WRITE); 130 std::wstring value; 131 if (key.ReadValue(name, &value) != ERROR_SUCCESS) 132 return false; 133 return (key.WriteValue(name, L"") == ERROR_SUCCESS); 134} 135 136bool RemoveGoogleUpdateStrKey(const wchar_t* const name) { 137 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 138 std::wstring reg_path = dist->GetStateKey(); 139 RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WRITE); 140 if (!key.HasValue(name)) 141 return true; 142 return (key.DeleteValue(name) == ERROR_SUCCESS); 143} 144 145bool GetChromeChannelInternal(bool system_install, 146 bool add_multi_modifier, 147 base::string16* channel) { 148 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 149 if (dist->GetChromeChannel(channel)) { 150 return true; 151 } 152 153 HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 154 base::string16 reg_path = dist->GetStateKey(); 155 RegKey key(root_key, reg_path.c_str(), KEY_READ); 156 157 installer::ChannelInfo channel_info; 158 if (!channel_info.Initialize(key)) { 159 channel->assign(installer::kChromeChannelUnknown); 160 return false; 161 } 162 163 if (!channel_info.GetChannelName(channel)) { 164 channel->assign(installer::kChromeChannelUnknown); 165 } 166 167 // Tag the channel name if this is a multi-install. 168 if (add_multi_modifier && channel_info.IsMultiInstall()) { 169 if (!channel->empty()) { 170 channel->append(1, L'-'); 171 } 172 channel->append(1, L'm'); 173 } 174 175 return true; 176} 177 178// Populates |update_policy| with the UpdatePolicy enum value corresponding to a 179// DWORD read from the registry and returns true if |value| is within range. 180// If |value| is out of range, returns false without modifying |update_policy|. 181bool GetUpdatePolicyFromDword( 182 const DWORD value, 183 GoogleUpdateSettings::UpdatePolicy* update_policy) { 184 switch (value) { 185 case GoogleUpdateSettings::UPDATES_DISABLED: 186 case GoogleUpdateSettings::AUTOMATIC_UPDATES: 187 case GoogleUpdateSettings::MANUAL_UPDATES_ONLY: 188 case GoogleUpdateSettings::AUTO_UPDATES_ONLY: 189 *update_policy = static_cast<GoogleUpdateSettings::UpdatePolicy>(value); 190 return true; 191 default: 192 LOG(WARNING) << "Unexpected update policy override value: " << value; 193 } 194 return false; 195} 196 197} // namespace 198 199bool GoogleUpdateSettings::IsSystemInstall() { 200 bool system_install = false; 201 base::FilePath module_dir; 202 if (!PathService::Get(base::DIR_MODULE, &module_dir)) { 203 LOG(WARNING) 204 << "Failed to get directory of module; assuming per-user install."; 205 } else { 206 system_install = !InstallUtil::IsPerUserInstall(module_dir.value().c_str()); 207 } 208 return system_install; 209} 210 211bool GoogleUpdateSettings::GetCollectStatsConsent() { 212 return GetCollectStatsConsentAtLevel(IsSystemInstall()); 213} 214 215// Older versions of Chrome unconditionally read from HKCU\...\ClientState\... 216// and then HKLM\...\ClientState\.... This means that system-level Chrome 217// never checked ClientStateMedium (which has priority according to Google 218// Update) and gave preference to a value in HKCU (which was never checked by 219// Google Update). From now on, Chrome follows Google Update's policy. 220bool GoogleUpdateSettings::GetCollectStatsConsentAtLevel(bool system_install) { 221 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 222 223 // Consent applies to all products in a multi-install package. 224 if (InstallUtil::IsMultiInstall(dist, system_install)) { 225 dist = BrowserDistribution::GetSpecificDistribution( 226 BrowserDistribution::CHROME_BINARIES); 227 } 228 229 RegKey key; 230 DWORD value = 0; 231 bool have_value = false; 232 233 // For system-level installs, try ClientStateMedium first. 234 have_value = 235 system_install && 236 key.Open(HKEY_LOCAL_MACHINE, dist->GetStateMediumKey().c_str(), 237 KEY_QUERY_VALUE) == ERROR_SUCCESS && 238 key.ReadValueDW(google_update::kRegUsageStatsField, 239 &value) == ERROR_SUCCESS; 240 241 // Otherwise, try ClientState. 242 if (!have_value) { 243 have_value = 244 key.Open(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, 245 dist->GetStateKey().c_str(), 246 KEY_QUERY_VALUE) == ERROR_SUCCESS && 247 key.ReadValueDW(google_update::kRegUsageStatsField, 248 &value) == ERROR_SUCCESS; 249 } 250 251 // Google Update specifically checks that the value is 1, so we do the same. 252 return have_value && value == 1; 253} 254 255bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented) { 256 return SetCollectStatsConsentAtLevel(IsSystemInstall(), consented); 257} 258 259bool GoogleUpdateSettings::SetCollectStatsConsentAtLevel(bool system_install, 260 bool consented) { 261 // Google Update writes and expects 1 for true, 0 for false. 262 DWORD value = consented ? 1 : 0; 263 264 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 265 266 // Consent applies to all products in a multi-install package. 267 if (InstallUtil::IsMultiInstall(dist, system_install)) { 268 dist = BrowserDistribution::GetSpecificDistribution( 269 BrowserDistribution::CHROME_BINARIES); 270 } 271 272 // Write to ClientStateMedium for system-level; ClientState otherwise. 273 HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 274 std::wstring reg_path = 275 system_install ? dist->GetStateMediumKey() : dist->GetStateKey(); 276 RegKey key; 277 LONG result = key.Create(root_key, reg_path.c_str(), KEY_SET_VALUE); 278 if (result != ERROR_SUCCESS) { 279 LOG(ERROR) << "Failed opening key " << reg_path << " to set " 280 << google_update::kRegUsageStatsField << "; result: " << result; 281 } else { 282 result = key.WriteValue(google_update::kRegUsageStatsField, value); 283 LOG_IF(ERROR, result != ERROR_SUCCESS) << "Failed setting " 284 << google_update::kRegUsageStatsField << " in key " << reg_path 285 << "; result: " << result; 286 } 287 return (result == ERROR_SUCCESS); 288} 289 290bool GoogleUpdateSettings::GetMetricsId(std::string* metrics_id) { 291 std::wstring metrics_id_w; 292 bool rv = ReadGoogleUpdateStrKey(google_update::kRegMetricsId, &metrics_id_w); 293 *metrics_id = base::WideToUTF8(metrics_id_w); 294 return rv; 295} 296 297bool GoogleUpdateSettings::SetMetricsId(const std::string& metrics_id) { 298 std::wstring metrics_id_w = base::UTF8ToWide(metrics_id); 299 return WriteGoogleUpdateStrKey(google_update::kRegMetricsId, metrics_id_w); 300} 301 302// EULA consent is only relevant for system-level installs. 303bool GoogleUpdateSettings::SetEULAConsent( 304 const InstallationState& machine_state, 305 BrowserDistribution* dist, 306 bool consented) { 307 DCHECK(dist); 308 const DWORD eula_accepted = consented ? 1 : 0; 309 std::wstring reg_path = dist->GetStateMediumKey(); 310 bool succeeded = true; 311 RegKey key; 312 313 // Write the consent value into the product's ClientStateMedium key. 314 if (key.Create(HKEY_LOCAL_MACHINE, reg_path.c_str(), 315 KEY_SET_VALUE) != ERROR_SUCCESS || 316 key.WriteValue(google_update::kRegEULAAceptedField, 317 eula_accepted) != ERROR_SUCCESS) { 318 succeeded = false; 319 } 320 321 // If this is a multi-install, also write it into the binaries' key. 322 // --mutli-install is not provided on the command-line, so deduce it from 323 // the product's state. 324 const installer::ProductState* product_state = 325 machine_state.GetProductState(true, dist->GetType()); 326 if (product_state != NULL && product_state->is_multi_install()) { 327 dist = BrowserDistribution::GetSpecificDistribution( 328 BrowserDistribution::CHROME_BINARIES); 329 reg_path = dist->GetStateMediumKey(); 330 if (key.Create(HKEY_LOCAL_MACHINE, reg_path.c_str(), 331 KEY_SET_VALUE) != ERROR_SUCCESS || 332 key.WriteValue(google_update::kRegEULAAceptedField, 333 eula_accepted) != ERROR_SUCCESS) { 334 succeeded = false; 335 } 336 } 337 338 return succeeded; 339} 340 341int GoogleUpdateSettings::GetLastRunTime() { 342 std::wstring time_s; 343 if (!ReadGoogleUpdateStrKey(google_update::kRegLastRunTimeField, &time_s)) 344 return -1; 345 int64 time_i; 346 if (!base::StringToInt64(time_s, &time_i)) 347 return -1; 348 base::TimeDelta td = 349 base::Time::NowFromSystemTime() - base::Time::FromInternalValue(time_i); 350 return td.InDays(); 351} 352 353bool GoogleUpdateSettings::SetLastRunTime() { 354 int64 time = base::Time::NowFromSystemTime().ToInternalValue(); 355 return WriteGoogleUpdateStrKey(google_update::kRegLastRunTimeField, 356 base::Int64ToString16(time)); 357} 358 359bool GoogleUpdateSettings::RemoveLastRunTime() { 360 return RemoveGoogleUpdateStrKey(google_update::kRegLastRunTimeField); 361} 362 363bool GoogleUpdateSettings::GetBrowser(std::wstring* browser) { 364 return ReadGoogleUpdateStrKey(google_update::kRegBrowserField, browser); 365} 366 367bool GoogleUpdateSettings::GetLanguage(std::wstring* language) { 368 return ReadGoogleUpdateStrKey(google_update::kRegLangField, language); 369} 370 371bool GoogleUpdateSettings::GetBrand(std::wstring* brand) { 372 return ReadGoogleUpdateStrKey(google_update::kRegRLZBrandField, brand); 373} 374 375bool GoogleUpdateSettings::GetReactivationBrand(std::wstring* brand) { 376 return ReadGoogleUpdateStrKey(google_update::kRegRLZReactivationBrandField, 377 brand); 378} 379 380bool GoogleUpdateSettings::GetClient(std::wstring* client) { 381 return ReadGoogleUpdateStrKey(google_update::kRegClientField, client); 382} 383 384bool GoogleUpdateSettings::SetClient(const std::wstring& client) { 385 return WriteGoogleUpdateStrKey(google_update::kRegClientField, client); 386} 387 388bool GoogleUpdateSettings::GetReferral(std::wstring* referral) { 389 return ReadGoogleUpdateStrKey(google_update::kRegReferralField, referral); 390} 391 392bool GoogleUpdateSettings::ClearReferral() { 393 return ClearGoogleUpdateStrKey(google_update::kRegReferralField); 394} 395 396bool GoogleUpdateSettings::UpdateDidRunState(bool did_run, 397 bool system_level) { 398 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 399 return UpdateDidRunStateForDistribution(dist, did_run, system_level); 400} 401 402bool GoogleUpdateSettings::UpdateDidRunStateForDistribution( 403 BrowserDistribution* dist, 404 bool did_run, 405 bool system_level) { 406 return WriteGoogleUpdateStrKeyMultiInstall(dist, 407 google_update::kRegDidRunField, 408 did_run ? L"1" : L"0", 409 system_level); 410} 411 412std::wstring GoogleUpdateSettings::GetChromeChannel(bool system_install) { 413 std::wstring channel; 414 GetChromeChannelInternal(system_install, false, &channel); 415 return channel; 416} 417 418bool GoogleUpdateSettings::GetChromeChannelAndModifiers( 419 bool system_install, 420 base::string16* channel) { 421 return GetChromeChannelInternal(system_install, true, channel); 422} 423 424void GoogleUpdateSettings::UpdateInstallStatus(bool system_install, 425 installer::ArchiveType archive_type, int install_return_code, 426 const std::wstring& product_guid) { 427 DCHECK(archive_type != installer::UNKNOWN_ARCHIVE_TYPE || 428 install_return_code != 0); 429 HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 430 431 RegKey key; 432 installer::ChannelInfo channel_info; 433 std::wstring reg_key(google_update::kRegPathClientState); 434 reg_key.append(L"\\"); 435 reg_key.append(product_guid); 436 LONG result = key.Open(reg_root, reg_key.c_str(), 437 KEY_QUERY_VALUE | KEY_SET_VALUE); 438 if (result == ERROR_SUCCESS) 439 channel_info.Initialize(key); 440 else if (result != ERROR_FILE_NOT_FOUND) 441 LOG(ERROR) << "Failed to open " << reg_key << "; Error: " << result; 442 443 if (UpdateGoogleUpdateApKey(archive_type, install_return_code, 444 &channel_info)) { 445 // We have a modified channel_info value to write. 446 // Create the app's ClientState key if it doesn't already exist. 447 if (!key.Valid()) { 448 result = key.Open(reg_root, google_update::kRegPathClientState, 449 KEY_CREATE_SUB_KEY); 450 if (result == ERROR_SUCCESS) 451 result = key.CreateKey(product_guid.c_str(), KEY_SET_VALUE); 452 453 if (result != ERROR_SUCCESS) { 454 LOG(ERROR) << "Failed to create " << reg_key << "; Error: " << result; 455 return; 456 } 457 } 458 if (!channel_info.Write(&key)) { 459 LOG(ERROR) << "Failed to write to application's ClientState key " 460 << google_update::kRegApField << " = " << channel_info.value(); 461 } 462 } 463} 464 465bool GoogleUpdateSettings::UpdateGoogleUpdateApKey( 466 installer::ArchiveType archive_type, int install_return_code, 467 installer::ChannelInfo* value) { 468 DCHECK(archive_type != installer::UNKNOWN_ARCHIVE_TYPE || 469 install_return_code != 0); 470 bool modified = false; 471 472 if (archive_type == installer::FULL_ARCHIVE_TYPE || !install_return_code) { 473 if (value->SetFullSuffix(false)) { 474 VLOG(1) << "Removed incremental installer failure key; " 475 "switching to channel: " 476 << value->value(); 477 modified = true; 478 } 479 } else if (archive_type == installer::INCREMENTAL_ARCHIVE_TYPE) { 480 if (value->SetFullSuffix(true)) { 481 VLOG(1) << "Incremental installer failed; switching to channel: " 482 << value->value(); 483 modified = true; 484 } else { 485 VLOG(1) << "Incremental installer failure; already on channel: " 486 << value->value(); 487 } 488 } else { 489 // It's okay if we don't know the archive type. In this case, leave the 490 // "-full" suffix as we found it. 491 DCHECK_EQ(installer::UNKNOWN_ARCHIVE_TYPE, archive_type); 492 } 493 494 if (value->SetMultiFailSuffix(false)) { 495 VLOG(1) << "Removed multi-install failure key; switching to channel: " 496 << value->value(); 497 modified = true; 498 } 499 500 return modified; 501} 502 503void GoogleUpdateSettings::UpdateProfileCounts(int profiles_active, 504 int profiles_signedin) { 505 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 506 bool system_install = IsSystemInstall(); 507 WriteGoogleUpdateStrKeyInternal(dist, system_install, 508 google_update::kRegProfilesActive, 509 base::Int64ToString16(profiles_active), 510 L"sum()"); 511 WriteGoogleUpdateStrKeyInternal(dist, system_install, 512 google_update::kRegProfilesSignedIn, 513 base::Int64ToString16(profiles_signedin), 514 L"sum()"); 515} 516 517int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() { 518 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 519 std::wstring reg_path = dist->GetStateKey(); 520 521 // Minimum access needed is to be able to write to this key. 522 RegKey reg_key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_SET_VALUE); 523 if (!reg_key.Valid()) 524 return 0; 525 526 HANDLE target_handle = 0; 527 if (!DuplicateHandle(GetCurrentProcess(), reg_key.Handle(), 528 GetCurrentProcess(), &target_handle, KEY_SET_VALUE, 529 TRUE, DUPLICATE_SAME_ACCESS)) { 530 return 0; 531 } 532 return reinterpret_cast<int>(target_handle); 533} 534 535bool GoogleUpdateSettings::WriteGoogleUpdateSystemClientKey( 536 int handle, const std::wstring& key, const std::wstring& value) { 537 HKEY reg_key = reinterpret_cast<HKEY>(reinterpret_cast<void*>(handle)); 538 DWORD size = static_cast<DWORD>(value.size()) * sizeof(wchar_t); 539 LSTATUS status = RegSetValueEx(reg_key, key.c_str(), 0, REG_SZ, 540 reinterpret_cast<const BYTE*>(value.c_str()), size); 541 return status == ERROR_SUCCESS; 542} 543 544GoogleUpdateSettings::UpdatePolicy GoogleUpdateSettings::GetAppUpdatePolicy( 545 const std::wstring& app_guid, 546 bool* is_overridden) { 547 bool found_override = false; 548 UpdatePolicy update_policy = kDefaultUpdatePolicy; 549 550#if defined(GOOGLE_CHROME_BUILD) 551 DCHECK(!app_guid.empty()); 552 RegKey policy_key; 553 554 // Google Update Group Policy settings are always in HKLM. 555 if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey, KEY_QUERY_VALUE) == 556 ERROR_SUCCESS) { 557 DWORD value = 0; 558 base::string16 app_update_override(kUpdateOverrideValuePrefix); 559 app_update_override.append(app_guid); 560 // First try to read and comprehend the app-specific override. 561 found_override = (policy_key.ReadValueDW(app_update_override.c_str(), 562 &value) == ERROR_SUCCESS && 563 GetUpdatePolicyFromDword(value, &update_policy)); 564 565 // Failing that, try to read and comprehend the default override. 566 if (!found_override && 567 policy_key.ReadValueDW(kUpdatePolicyValue, &value) == ERROR_SUCCESS) { 568 GetUpdatePolicyFromDword(value, &update_policy); 569 } 570 } 571#endif // defined(GOOGLE_CHROME_BUILD) 572 573 if (is_overridden != NULL) 574 *is_overridden = found_override; 575 576 return update_policy; 577} 578 579// static 580bool GoogleUpdateSettings::AreAutoupdatesEnabled( 581 const base::string16& app_guid) { 582 // Check the auto-update check period override. If it is 0 or exceeds the 583 // maximum timeout, then for all intents and purposes auto updates are 584 // disabled. 585 RegKey policy_key; 586 DWORD value = 0; 587 if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey, 588 KEY_QUERY_VALUE) == ERROR_SUCCESS && 589 policy_key.ReadValueDW(kCheckPeriodOverrideMinutes, 590 &value) == ERROR_SUCCESS && 591 (value == 0 || value > kCheckPeriodOverrideMinutesMax)) { 592 return false; 593 } 594 595 UpdatePolicy policy = GetAppUpdatePolicy(app_guid, NULL); 596 return (policy == AUTOMATIC_UPDATES || policy == AUTO_UPDATES_ONLY); 597} 598 599// static 600bool GoogleUpdateSettings::ReenableAutoupdatesForApp( 601 const base::string16& app_guid) { 602#if defined(GOOGLE_CHROME_BUILD) 603 int needs_reset_count = 0; 604 int did_reset_count = 0; 605 606 UpdatePolicy update_policy = kDefaultUpdatePolicy; 607 RegKey policy_key; 608 if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey, 609 KEY_SET_VALUE | KEY_QUERY_VALUE) == ERROR_SUCCESS) { 610 // First check the app-specific override value and reset that if needed. 611 // Note that this intentionally sets the override to AUTOMATIC_UPDATES 612 // even if it was previously AUTO_UPDATES_ONLY. The thinking is that 613 // AUTOMATIC_UPDATES is marginally more likely to let a user update and this 614 // code is only called when a stuck user asks for updates. 615 base::string16 app_update_override(kUpdateOverrideValuePrefix); 616 app_update_override.append(app_guid); 617 DWORD value = 0; 618 bool has_app_update_override = 619 policy_key.ReadValueDW(app_update_override.c_str(), 620 &value) == ERROR_SUCCESS; 621 if (has_app_update_override && 622 (!GetUpdatePolicyFromDword(value, &update_policy) || 623 update_policy != GoogleUpdateSettings::AUTOMATIC_UPDATES)) { 624 ++needs_reset_count; 625 if (policy_key.WriteValue( 626 app_update_override.c_str(), 627 static_cast<DWORD>(GoogleUpdateSettings::AUTOMATIC_UPDATES)) == 628 ERROR_SUCCESS) { 629 ++did_reset_count; 630 } 631 } 632 633 // If there was no app-specific override policy see if there's a global 634 // policy preventing updates and delete it if so. 635 if (!has_app_update_override && 636 policy_key.ReadValueDW(kUpdatePolicyValue, &value) == ERROR_SUCCESS && 637 (!GetUpdatePolicyFromDword(value, &update_policy) || 638 update_policy != GoogleUpdateSettings::AUTOMATIC_UPDATES)) { 639 ++needs_reset_count; 640 if (policy_key.DeleteValue(kUpdatePolicyValue) == ERROR_SUCCESS) 641 ++did_reset_count; 642 } 643 644 // Check the auto-update check period override. If it is 0 or exceeds 645 // the maximum timeout, delete the override value. 646 if (policy_key.ReadValueDW(kCheckPeriodOverrideMinutes, 647 &value) == ERROR_SUCCESS && 648 (value == 0 || value > kCheckPeriodOverrideMinutesMax)) { 649 ++needs_reset_count; 650 if (policy_key.DeleteValue(kCheckPeriodOverrideMinutes) == ERROR_SUCCESS) 651 ++did_reset_count; 652 } 653 654 // Return whether the number of successful resets is the same as the 655 // number of things that appeared to need resetting. 656 return (needs_reset_count == did_reset_count); 657 } else { 658 // For some reason we couldn't open the policy key with the desired 659 // permissions to make changes (the most likely reason is that there is no 660 // policy set). Simply return whether or not we think updates are enabled. 661 return AreAutoupdatesEnabled(app_guid); 662 } 663 664#endif 665 // Non Google Chrome isn't going to autoupdate. 666 return true; 667} 668 669void GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms() { 670 const bool is_multi_install = InstallUtil::IsMultiInstall( 671 BrowserDistribution::GetDistribution(), IsSystemInstall()); 672 const base::string16 app_guid = 673 BrowserDistribution::GetSpecificDistribution( 674 is_multi_install ? BrowserDistribution::CHROME_BINARIES : 675 BrowserDistribution::CHROME_BROWSER)->GetAppGuid(); 676 677 bool is_overridden = false; 678 const UpdatePolicy update_policy = GetAppUpdatePolicy(app_guid, 679 &is_overridden); 680 UMA_HISTOGRAM_BOOLEAN("GoogleUpdate.UpdatePolicyIsOverridden", is_overridden); 681 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.EffectivePolicy", update_policy, 682 UPDATE_POLICIES_COUNT); 683} 684 685base::string16 GoogleUpdateSettings::GetUninstallCommandLine( 686 bool system_install) { 687 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 688 base::string16 cmd_line; 689 RegKey update_key; 690 691 if (update_key.Open(root_key, google_update::kRegPathGoogleUpdate, 692 KEY_QUERY_VALUE) == ERROR_SUCCESS) { 693 update_key.ReadValue(google_update::kRegUninstallCmdLine, &cmd_line); 694 } 695 696 return cmd_line; 697} 698 699Version GoogleUpdateSettings::GetGoogleUpdateVersion(bool system_install) { 700 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 701 base::string16 version; 702 RegKey key; 703 704 if (key.Open(root_key, 705 google_update::kRegPathGoogleUpdate, 706 KEY_QUERY_VALUE) == ERROR_SUCCESS && 707 key.ReadValue(google_update::kRegGoogleUpdateVersion, 708 &version) == ERROR_SUCCESS) { 709 return Version(base::UTF16ToUTF8(version)); 710 } 711 712 return Version(); 713} 714 715base::Time GoogleUpdateSettings::GetGoogleUpdateLastStartedAU( 716 bool system_install) { 717 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 718 RegKey update_key; 719 720 if (update_key.Open(root_key, google_update::kRegPathGoogleUpdate, 721 KEY_QUERY_VALUE) == ERROR_SUCCESS) { 722 DWORD last_start; 723 if (update_key.ReadValueDW(google_update::kRegLastStartedAUField, 724 &last_start) == ERROR_SUCCESS) { 725 return base::Time::FromTimeT(last_start); 726 } 727 } 728 729 return base::Time(); 730} 731 732base::Time GoogleUpdateSettings::GetGoogleUpdateLastChecked( 733 bool system_install) { 734 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 735 RegKey update_key; 736 737 if (update_key.Open(root_key, google_update::kRegPathGoogleUpdate, 738 KEY_QUERY_VALUE) == ERROR_SUCCESS) { 739 DWORD last_check; 740 if (update_key.ReadValueDW(google_update::kRegLastCheckedField, 741 &last_check) == ERROR_SUCCESS) { 742 return base::Time::FromTimeT(last_check); 743 } 744 } 745 746 return base::Time(); 747} 748 749bool GoogleUpdateSettings::GetUpdateDetailForApp(bool system_install, 750 const wchar_t* app_guid, 751 ProductData* data) { 752 DCHECK(app_guid); 753 DCHECK(data); 754 755 bool product_found = false; 756 757 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 758 base::string16 clientstate_reg_path(google_update::kRegPathClientState); 759 clientstate_reg_path.append(L"\\"); 760 clientstate_reg_path.append(app_guid); 761 762 RegKey clientstate; 763 if (clientstate.Open(root_key, clientstate_reg_path.c_str(), 764 KEY_QUERY_VALUE) == ERROR_SUCCESS) { 765 base::string16 version; 766 DWORD dword_value; 767 if ((clientstate.ReadValueDW(google_update::kRegLastCheckSuccessField, 768 &dword_value) == ERROR_SUCCESS) && 769 (clientstate.ReadValue(google_update::kRegVersionField, 770 &version) == ERROR_SUCCESS)) { 771 product_found = true; 772 data->version = base::UTF16ToASCII(version); 773 data->last_success = base::Time::FromTimeT(dword_value); 774 data->last_result = 0; 775 data->last_error_code = 0; 776 data->last_extra_code = 0; 777 778 if (clientstate.ReadValueDW(google_update::kRegLastInstallerResultField, 779 &dword_value) == ERROR_SUCCESS) { 780 // Google Update convention is that if an installer writes an result 781 // code that is invalid, it is clamped to an exit code result. 782 const DWORD kMaxValidInstallResult = 4; // INSTALLER_RESULT_EXIT_CODE 783 data->last_result = std::min(dword_value, kMaxValidInstallResult); 784 } 785 if (clientstate.ReadValueDW(google_update::kRegLastInstallerErrorField, 786 &dword_value) == ERROR_SUCCESS) { 787 data->last_error_code = dword_value; 788 } 789 if (clientstate.ReadValueDW(google_update::kRegLastInstallerExtraField, 790 &dword_value) == ERROR_SUCCESS) { 791 data->last_extra_code = dword_value; 792 } 793 } 794 } 795 796 return product_found; 797} 798 799bool GoogleUpdateSettings::GetUpdateDetailForGoogleUpdate(bool system_install, 800 ProductData* data) { 801 return GetUpdateDetailForApp(system_install, 802 google_update::kGoogleUpdateUpgradeCode, 803 data); 804} 805 806bool GoogleUpdateSettings::GetUpdateDetail(bool system_install, 807 ProductData* data) { 808 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 809 return GetUpdateDetailForApp(system_install, 810 dist->GetAppGuid().c_str(), 811 data); 812} 813 814bool GoogleUpdateSettings::SetExperimentLabels( 815 bool system_install, 816 const base::string16& experiment_labels) { 817 HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 818 819 // Use the browser distribution and install level to write to the correct 820 // client state/app guid key. 821 bool success = false; 822 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 823 if (dist->ShouldSetExperimentLabels()) { 824 base::string16 client_state_path( 825 system_install ? dist->GetStateMediumKey() : dist->GetStateKey()); 826 RegKey client_state( 827 reg_root, client_state_path.c_str(), KEY_SET_VALUE); 828 if (experiment_labels.empty()) { 829 success = client_state.DeleteValue(google_update::kExperimentLabels) 830 == ERROR_SUCCESS; 831 } else { 832 success = client_state.WriteValue(google_update::kExperimentLabels, 833 experiment_labels.c_str()) == ERROR_SUCCESS; 834 } 835 } 836 837 return success; 838} 839 840bool GoogleUpdateSettings::ReadExperimentLabels( 841 bool system_install, 842 base::string16* experiment_labels) { 843 HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 844 845 // If this distribution does not set the experiment labels, don't bother 846 // reading. 847 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 848 if (!dist->ShouldSetExperimentLabels()) 849 return false; 850 851 base::string16 client_state_path( 852 system_install ? dist->GetStateMediumKey() : dist->GetStateKey()); 853 854 RegKey client_state; 855 LONG result = 856 client_state.Open(reg_root, client_state_path.c_str(), KEY_QUERY_VALUE); 857 if (result == ERROR_SUCCESS) { 858 result = client_state.ReadValue(google_update::kExperimentLabels, 859 experiment_labels); 860 } 861 862 // If the key or value was not present, return the empty string. 863 if (result == ERROR_FILE_NOT_FOUND || result == ERROR_PATH_NOT_FOUND) { 864 experiment_labels->clear(); 865 return true; 866 } 867 868 return result == ERROR_SUCCESS; 869} 870