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