google_update_settings.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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 299scoped_ptr<metrics::ClientInfo> GoogleUpdateSettings::LoadMetricsClientInfo() { 300 base::string16 client_id_16; 301 if (!ReadGoogleUpdateStrKey(google_update::kRegMetricsId, &client_id_16) || 302 client_id_16.empty()) { 303 return scoped_ptr<metrics::ClientInfo>(); 304 } 305 306 scoped_ptr<metrics::ClientInfo> client_info(new metrics::ClientInfo); 307 client_info->client_id = base::UTF16ToUTF8(client_id_16); 308 309 base::string16 installation_date_str; 310 if (ReadGoogleUpdateStrKey(google_update::kRegMetricsIdInstallDate, 311 &installation_date_str)) { 312 base::StringToInt64(installation_date_str, &client_info->installation_date); 313 } 314 315 base::string16 reporting_enbaled_date_date_str; 316 if (ReadGoogleUpdateStrKey(google_update::kRegMetricsIdEnabledDate, 317 &reporting_enbaled_date_date_str)) { 318 base::StringToInt64(reporting_enbaled_date_date_str, 319 &client_info->reporting_enabled_date); 320 } 321 322 return client_info.Pass(); 323} 324 325void GoogleUpdateSettings::StoreMetricsClientInfo( 326 const metrics::ClientInfo& client_info) { 327 // Attempt a best-effort at backing |client_info| in the registry (but don't 328 // handle/report failures). 329 WriteGoogleUpdateStrKey(google_update::kRegMetricsId, 330 base::UTF8ToUTF16(client_info.client_id)); 331 WriteGoogleUpdateStrKey(google_update::kRegMetricsIdInstallDate, 332 base::Int64ToString16(client_info.installation_date)); 333 WriteGoogleUpdateStrKey( 334 google_update::kRegMetricsIdEnabledDate, 335 base::Int64ToString16(client_info.reporting_enabled_date)); 336} 337 338// EULA consent is only relevant for system-level installs. 339bool GoogleUpdateSettings::SetEULAConsent( 340 const InstallationState& machine_state, 341 BrowserDistribution* dist, 342 bool consented) { 343 DCHECK(dist); 344 const DWORD eula_accepted = consented ? 1 : 0; 345 const REGSAM kAccess = KEY_SET_VALUE | KEY_WOW64_32KEY; 346 base::string16 reg_path = dist->GetStateMediumKey(); 347 bool succeeded = true; 348 RegKey key; 349 350 // Write the consent value into the product's ClientStateMedium key. 351 if (key.Create(HKEY_LOCAL_MACHINE, reg_path.c_str(), 352 kAccess) != ERROR_SUCCESS || 353 key.WriteValue(google_update::kRegEULAAceptedField, 354 eula_accepted) != ERROR_SUCCESS) { 355 succeeded = false; 356 } 357 358 // If this is a multi-install, also write it into the binaries' key. 359 // --mutli-install is not provided on the command-line, so deduce it from 360 // the product's state. 361 const installer::ProductState* product_state = 362 machine_state.GetProductState(true, dist->GetType()); 363 if (product_state != NULL && product_state->is_multi_install()) { 364 dist = BrowserDistribution::GetSpecificDistribution( 365 BrowserDistribution::CHROME_BINARIES); 366 reg_path = dist->GetStateMediumKey(); 367 if (key.Create(HKEY_LOCAL_MACHINE, reg_path.c_str(), 368 kAccess) != ERROR_SUCCESS || 369 key.WriteValue(google_update::kRegEULAAceptedField, 370 eula_accepted) != ERROR_SUCCESS) { 371 succeeded = false; 372 } 373 } 374 375 return succeeded; 376} 377 378int GoogleUpdateSettings::GetLastRunTime() { 379 base::string16 time_s; 380 if (!ReadGoogleUpdateStrKey(google_update::kRegLastRunTimeField, &time_s)) 381 return -1; 382 int64 time_i; 383 if (!base::StringToInt64(time_s, &time_i)) 384 return -1; 385 base::TimeDelta td = 386 base::Time::NowFromSystemTime() - base::Time::FromInternalValue(time_i); 387 return td.InDays(); 388} 389 390bool GoogleUpdateSettings::SetLastRunTime() { 391 int64 time = base::Time::NowFromSystemTime().ToInternalValue(); 392 return WriteGoogleUpdateStrKey(google_update::kRegLastRunTimeField, 393 base::Int64ToString16(time)); 394} 395 396bool GoogleUpdateSettings::RemoveLastRunTime() { 397 return RemoveGoogleUpdateStrKey(google_update::kRegLastRunTimeField); 398} 399 400bool GoogleUpdateSettings::GetBrowser(base::string16* browser) { 401 return ReadGoogleUpdateStrKey(google_update::kRegBrowserField, browser); 402} 403 404bool GoogleUpdateSettings::GetLanguage(base::string16* language) { 405 return ReadGoogleUpdateStrKey(google_update::kRegLangField, language); 406} 407 408bool GoogleUpdateSettings::GetBrand(base::string16* brand) { 409 return ReadGoogleUpdateStrKey(google_update::kRegRLZBrandField, brand); 410} 411 412bool GoogleUpdateSettings::GetReactivationBrand(base::string16* brand) { 413 return ReadGoogleUpdateStrKey(google_update::kRegRLZReactivationBrandField, 414 brand); 415} 416 417bool GoogleUpdateSettings::GetClient(base::string16* client) { 418 return ReadGoogleUpdateStrKey(google_update::kRegClientField, client); 419} 420 421bool GoogleUpdateSettings::SetClient(const base::string16& client) { 422 return WriteGoogleUpdateStrKey(google_update::kRegClientField, client); 423} 424 425bool GoogleUpdateSettings::GetReferral(base::string16* referral) { 426 return ReadGoogleUpdateStrKey(google_update::kRegReferralField, referral); 427} 428 429bool GoogleUpdateSettings::ClearReferral() { 430 return ClearGoogleUpdateStrKey(google_update::kRegReferralField); 431} 432 433bool GoogleUpdateSettings::UpdateDidRunStateForApp( 434 const AppRegistrationData& app_reg_data, 435 bool did_run) { 436 return WriteGoogleUpdateStrKeyInternal(app_reg_data, 437 false, // user level. 438 google_update::kRegDidRunField, 439 did_run ? L"1" : L"0", 440 NULL); 441} 442 443bool GoogleUpdateSettings::UpdateDidRunState(bool did_run, bool system_level) { 444 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 445 bool result = UpdateDidRunStateForApp(dist->GetAppRegistrationData(), 446 did_run); 447 // Update state for binaries, even if the previous call was unsuccessful. 448 if (InstallUtil::IsMultiInstall(dist, system_level)) 449 result = UpdateDidRunStateForBinaries(did_run) && result; 450 return result; 451} 452 453base::string16 GoogleUpdateSettings::GetChromeChannel(bool system_install) { 454 base::string16 channel; 455 GetChromeChannelInternal(system_install, false, &channel); 456 return channel; 457} 458 459bool GoogleUpdateSettings::GetChromeChannelAndModifiers( 460 bool system_install, 461 base::string16* channel) { 462 return GetChromeChannelInternal(system_install, true, channel); 463} 464 465void GoogleUpdateSettings::UpdateInstallStatus(bool system_install, 466 installer::ArchiveType archive_type, int install_return_code, 467 const base::string16& product_guid) { 468 DCHECK(archive_type != installer::UNKNOWN_ARCHIVE_TYPE || 469 install_return_code != 0); 470 HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 471 472 RegKey key; 473 installer::ChannelInfo channel_info; 474 base::string16 reg_key(google_update::kRegPathClientState); 475 reg_key.append(L"\\"); 476 reg_key.append(product_guid); 477 LONG result = key.Open(reg_root, 478 reg_key.c_str(), 479 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY); 480 if (result == ERROR_SUCCESS) 481 channel_info.Initialize(key); 482 else if (result != ERROR_FILE_NOT_FOUND) 483 LOG(ERROR) << "Failed to open " << reg_key << "; Error: " << result; 484 485 if (UpdateGoogleUpdateApKey(archive_type, install_return_code, 486 &channel_info)) { 487 // We have a modified channel_info value to write. 488 // Create the app's ClientState key if it doesn't already exist. 489 if (!key.Valid()) { 490 result = key.Open(reg_root, 491 google_update::kRegPathClientState, 492 KEY_CREATE_SUB_KEY | KEY_WOW64_32KEY); 493 if (result == ERROR_SUCCESS) 494 result = key.CreateKey(product_guid.c_str(), 495 KEY_SET_VALUE | KEY_WOW64_32KEY); 496 497 if (result != ERROR_SUCCESS) { 498 LOG(ERROR) << "Failed to create " << reg_key << "; Error: " << result; 499 return; 500 } 501 } 502 if (!channel_info.Write(&key)) { 503 LOG(ERROR) << "Failed to write to application's ClientState key " 504 << google_update::kRegApField << " = " << channel_info.value(); 505 } 506 } 507} 508 509bool GoogleUpdateSettings::UpdateGoogleUpdateApKey( 510 installer::ArchiveType archive_type, int install_return_code, 511 installer::ChannelInfo* value) { 512 DCHECK(archive_type != installer::UNKNOWN_ARCHIVE_TYPE || 513 install_return_code != 0); 514 bool modified = false; 515 516 if (archive_type == installer::FULL_ARCHIVE_TYPE || !install_return_code) { 517 if (value->SetFullSuffix(false)) { 518 VLOG(1) << "Removed incremental installer failure key; " 519 "switching to channel: " 520 << value->value(); 521 modified = true; 522 } 523 } else if (archive_type == installer::INCREMENTAL_ARCHIVE_TYPE) { 524 if (value->SetFullSuffix(true)) { 525 VLOG(1) << "Incremental installer failed; switching to channel: " 526 << value->value(); 527 modified = true; 528 } else { 529 VLOG(1) << "Incremental installer failure; already on channel: " 530 << value->value(); 531 } 532 } else { 533 // It's okay if we don't know the archive type. In this case, leave the 534 // "-full" suffix as we found it. 535 DCHECK_EQ(installer::UNKNOWN_ARCHIVE_TYPE, archive_type); 536 } 537 538 if (value->SetMultiFailSuffix(false)) { 539 VLOG(1) << "Removed multi-install failure key; switching to channel: " 540 << value->value(); 541 modified = true; 542 } 543 544 return modified; 545} 546 547void GoogleUpdateSettings::UpdateProfileCounts(int profiles_active, 548 int profiles_signedin) { 549 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 550 bool system_install = IsSystemInstall(); 551 WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(), 552 system_install, 553 google_update::kRegProfilesActive, 554 base::Int64ToString16(profiles_active), 555 L"sum()"); 556 WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(), 557 system_install, 558 google_update::kRegProfilesSignedIn, 559 base::Int64ToString16(profiles_signedin), 560 L"sum()"); 561} 562 563int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() { 564 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 565 base::string16 reg_path = dist->GetStateKey(); 566 567 // Minimum access needed is to be able to write to this key. 568 RegKey reg_key( 569 HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_SET_VALUE | KEY_WOW64_32KEY); 570 if (!reg_key.Valid()) 571 return 0; 572 573 HANDLE target_handle = 0; 574 if (!DuplicateHandle(GetCurrentProcess(), reg_key.Handle(), 575 GetCurrentProcess(), &target_handle, KEY_SET_VALUE, 576 TRUE, DUPLICATE_SAME_ACCESS)) { 577 return 0; 578 } 579 return reinterpret_cast<int>(target_handle); 580} 581 582bool GoogleUpdateSettings::WriteGoogleUpdateSystemClientKey( 583 int handle, const base::string16& key, const base::string16& value) { 584 HKEY reg_key = reinterpret_cast<HKEY>(reinterpret_cast<void*>(handle)); 585 DWORD size = static_cast<DWORD>(value.size()) * sizeof(wchar_t); 586 LSTATUS status = RegSetValueEx(reg_key, key.c_str(), 0, REG_SZ, 587 reinterpret_cast<const BYTE*>(value.c_str()), size); 588 return status == ERROR_SUCCESS; 589} 590 591GoogleUpdateSettings::UpdatePolicy GoogleUpdateSettings::GetAppUpdatePolicy( 592 const base::string16& app_guid, 593 bool* is_overridden) { 594 bool found_override = false; 595 UpdatePolicy update_policy = kDefaultUpdatePolicy; 596 597#if defined(GOOGLE_CHROME_BUILD) 598 DCHECK(!app_guid.empty()); 599 RegKey policy_key; 600 601 // Google Update Group Policy settings are always in HKLM. 602 // TODO(wfh): Check if policies should go into Wow6432Node or not. 603 if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey, KEY_QUERY_VALUE) == 604 ERROR_SUCCESS) { 605 DWORD value = 0; 606 base::string16 app_update_override(kUpdateOverrideValuePrefix); 607 app_update_override.append(app_guid); 608 // First try to read and comprehend the app-specific override. 609 found_override = (policy_key.ReadValueDW(app_update_override.c_str(), 610 &value) == ERROR_SUCCESS && 611 GetUpdatePolicyFromDword(value, &update_policy)); 612 613 // Failing that, try to read and comprehend the default override. 614 if (!found_override && 615 policy_key.ReadValueDW(kUpdatePolicyValue, &value) == ERROR_SUCCESS) { 616 GetUpdatePolicyFromDword(value, &update_policy); 617 } 618 } 619#endif // defined(GOOGLE_CHROME_BUILD) 620 621 if (is_overridden != NULL) 622 *is_overridden = found_override; 623 624 return update_policy; 625} 626 627// static 628bool GoogleUpdateSettings::AreAutoupdatesEnabled( 629 const base::string16& app_guid) { 630 // Check the auto-update check period override. If it is 0 or exceeds the 631 // maximum timeout, then for all intents and purposes auto updates are 632 // disabled. 633 RegKey policy_key; 634 DWORD value = 0; 635 if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey, 636 KEY_QUERY_VALUE) == ERROR_SUCCESS && 637 policy_key.ReadValueDW(kCheckPeriodOverrideMinutes, 638 &value) == ERROR_SUCCESS && 639 (value == 0 || value > kCheckPeriodOverrideMinutesMax)) { 640 return false; 641 } 642 643 UpdatePolicy policy = GetAppUpdatePolicy(app_guid, NULL); 644 return (policy == AUTOMATIC_UPDATES || policy == AUTO_UPDATES_ONLY); 645} 646 647// static 648bool GoogleUpdateSettings::ReenableAutoupdatesForApp( 649 const base::string16& app_guid) { 650#if defined(GOOGLE_CHROME_BUILD) 651 int needs_reset_count = 0; 652 int did_reset_count = 0; 653 654 UpdatePolicy update_policy = kDefaultUpdatePolicy; 655 RegKey policy_key; 656 if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey, 657 KEY_SET_VALUE | KEY_QUERY_VALUE) == ERROR_SUCCESS) { 658 // First check the app-specific override value and reset that if needed. 659 // Note that this intentionally sets the override to AUTOMATIC_UPDATES 660 // even if it was previously AUTO_UPDATES_ONLY. The thinking is that 661 // AUTOMATIC_UPDATES is marginally more likely to let a user update and this 662 // code is only called when a stuck user asks for updates. 663 base::string16 app_update_override(kUpdateOverrideValuePrefix); 664 app_update_override.append(app_guid); 665 DWORD value = 0; 666 bool has_app_update_override = 667 policy_key.ReadValueDW(app_update_override.c_str(), 668 &value) == ERROR_SUCCESS; 669 if (has_app_update_override && 670 (!GetUpdatePolicyFromDword(value, &update_policy) || 671 update_policy != GoogleUpdateSettings::AUTOMATIC_UPDATES)) { 672 ++needs_reset_count; 673 if (policy_key.WriteValue( 674 app_update_override.c_str(), 675 static_cast<DWORD>(GoogleUpdateSettings::AUTOMATIC_UPDATES)) == 676 ERROR_SUCCESS) { 677 ++did_reset_count; 678 } 679 } 680 681 // If there was no app-specific override policy see if there's a global 682 // policy preventing updates and delete it if so. 683 if (!has_app_update_override && 684 policy_key.ReadValueDW(kUpdatePolicyValue, &value) == ERROR_SUCCESS && 685 (!GetUpdatePolicyFromDword(value, &update_policy) || 686 update_policy != GoogleUpdateSettings::AUTOMATIC_UPDATES)) { 687 ++needs_reset_count; 688 if (policy_key.DeleteValue(kUpdatePolicyValue) == ERROR_SUCCESS) 689 ++did_reset_count; 690 } 691 692 // Check the auto-update check period override. If it is 0 or exceeds 693 // the maximum timeout, delete the override value. 694 if (policy_key.ReadValueDW(kCheckPeriodOverrideMinutes, 695 &value) == ERROR_SUCCESS && 696 (value == 0 || value > kCheckPeriodOverrideMinutesMax)) { 697 ++needs_reset_count; 698 if (policy_key.DeleteValue(kCheckPeriodOverrideMinutes) == ERROR_SUCCESS) 699 ++did_reset_count; 700 } 701 702 // Return whether the number of successful resets is the same as the 703 // number of things that appeared to need resetting. 704 return (needs_reset_count == did_reset_count); 705 } else { 706 // For some reason we couldn't open the policy key with the desired 707 // permissions to make changes (the most likely reason is that there is no 708 // policy set). Simply return whether or not we think updates are enabled. 709 return AreAutoupdatesEnabled(app_guid); 710 } 711 712#endif 713 // Non Google Chrome isn't going to autoupdate. 714 return true; 715} 716 717void GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms() { 718 const bool is_multi_install = InstallUtil::IsMultiInstall( 719 BrowserDistribution::GetDistribution(), IsSystemInstall()); 720 const base::string16 app_guid = 721 BrowserDistribution::GetSpecificDistribution( 722 is_multi_install ? BrowserDistribution::CHROME_BINARIES : 723 BrowserDistribution::CHROME_BROWSER)->GetAppGuid(); 724 725 bool is_overridden = false; 726 const UpdatePolicy update_policy = GetAppUpdatePolicy(app_guid, 727 &is_overridden); 728 UMA_HISTOGRAM_BOOLEAN("GoogleUpdate.UpdatePolicyIsOverridden", is_overridden); 729 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.EffectivePolicy", update_policy, 730 UPDATE_POLICIES_COUNT); 731} 732 733base::string16 GoogleUpdateSettings::GetUninstallCommandLine( 734 bool system_install) { 735 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 736 base::string16 cmd_line; 737 RegKey update_key; 738 739 if (update_key.Open(root_key, google_update::kRegPathGoogleUpdate, 740 KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) { 741 update_key.ReadValue(google_update::kRegUninstallCmdLine, &cmd_line); 742 } 743 744 return cmd_line; 745} 746 747Version GoogleUpdateSettings::GetGoogleUpdateVersion(bool system_install) { 748 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 749 base::string16 version; 750 RegKey key; 751 752 if (key.Open(root_key, 753 google_update::kRegPathGoogleUpdate, 754 KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS && 755 key.ReadValue(google_update::kRegGoogleUpdateVersion, &version) == 756 ERROR_SUCCESS) { 757 return Version(base::UTF16ToUTF8(version)); 758 } 759 760 return Version(); 761} 762 763base::Time GoogleUpdateSettings::GetGoogleUpdateLastStartedAU( 764 bool system_install) { 765 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 766 RegKey update_key; 767 768 if (update_key.Open(root_key, 769 google_update::kRegPathGoogleUpdate, 770 KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) { 771 DWORD last_start; 772 if (update_key.ReadValueDW(google_update::kRegLastStartedAUField, 773 &last_start) == ERROR_SUCCESS) { 774 return base::Time::FromTimeT(last_start); 775 } 776 } 777 778 return base::Time(); 779} 780 781base::Time GoogleUpdateSettings::GetGoogleUpdateLastChecked( 782 bool system_install) { 783 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 784 RegKey update_key; 785 786 if (update_key.Open(root_key, 787 google_update::kRegPathGoogleUpdate, 788 KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) { 789 DWORD last_check; 790 if (update_key.ReadValueDW(google_update::kRegLastCheckedField, 791 &last_check) == ERROR_SUCCESS) { 792 return base::Time::FromTimeT(last_check); 793 } 794 } 795 796 return base::Time(); 797} 798 799bool GoogleUpdateSettings::GetUpdateDetailForApp(bool system_install, 800 const wchar_t* app_guid, 801 ProductData* data) { 802 DCHECK(app_guid); 803 DCHECK(data); 804 805 bool product_found = false; 806 807 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 808 base::string16 clientstate_reg_path(google_update::kRegPathClientState); 809 clientstate_reg_path.append(L"\\"); 810 clientstate_reg_path.append(app_guid); 811 812 RegKey clientstate; 813 if (clientstate.Open(root_key, 814 clientstate_reg_path.c_str(), 815 KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) { 816 base::string16 version; 817 DWORD dword_value; 818 if ((clientstate.ReadValueDW(google_update::kRegLastCheckSuccessField, 819 &dword_value) == ERROR_SUCCESS) && 820 (clientstate.ReadValue(google_update::kRegVersionField, 821 &version) == ERROR_SUCCESS)) { 822 product_found = true; 823 data->version = base::UTF16ToASCII(version); 824 data->last_success = base::Time::FromTimeT(dword_value); 825 data->last_result = 0; 826 data->last_error_code = 0; 827 data->last_extra_code = 0; 828 829 if (clientstate.ReadValueDW(google_update::kRegLastInstallerResultField, 830 &dword_value) == ERROR_SUCCESS) { 831 // Google Update convention is that if an installer writes an result 832 // code that is invalid, it is clamped to an exit code result. 833 const DWORD kMaxValidInstallResult = 4; // INSTALLER_RESULT_EXIT_CODE 834 data->last_result = std::min(dword_value, kMaxValidInstallResult); 835 } 836 if (clientstate.ReadValueDW(google_update::kRegLastInstallerErrorField, 837 &dword_value) == ERROR_SUCCESS) { 838 data->last_error_code = dword_value; 839 } 840 if (clientstate.ReadValueDW(google_update::kRegLastInstallerExtraField, 841 &dword_value) == ERROR_SUCCESS) { 842 data->last_extra_code = dword_value; 843 } 844 } 845 } 846 847 return product_found; 848} 849 850bool GoogleUpdateSettings::GetUpdateDetailForGoogleUpdate(bool system_install, 851 ProductData* data) { 852 return GetUpdateDetailForApp(system_install, 853 google_update::kGoogleUpdateUpgradeCode, 854 data); 855} 856 857bool GoogleUpdateSettings::GetUpdateDetail(bool system_install, 858 ProductData* data) { 859 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 860 return GetUpdateDetailForApp(system_install, 861 dist->GetAppGuid().c_str(), 862 data); 863} 864 865bool GoogleUpdateSettings::SetExperimentLabels( 866 bool system_install, 867 const base::string16& experiment_labels) { 868 HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 869 870 // Use the browser distribution and install level to write to the correct 871 // client state/app guid key. 872 bool success = false; 873 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 874 if (dist->ShouldSetExperimentLabels()) { 875 base::string16 client_state_path( 876 system_install ? dist->GetStateMediumKey() : dist->GetStateKey()); 877 RegKey client_state( 878 reg_root, client_state_path.c_str(), KEY_SET_VALUE | KEY_WOW64_32KEY); 879 if (experiment_labels.empty()) { 880 success = client_state.DeleteValue(google_update::kExperimentLabels) 881 == ERROR_SUCCESS; 882 } else { 883 success = client_state.WriteValue(google_update::kExperimentLabels, 884 experiment_labels.c_str()) == ERROR_SUCCESS; 885 } 886 } 887 888 return success; 889} 890 891bool GoogleUpdateSettings::ReadExperimentLabels( 892 bool system_install, 893 base::string16* experiment_labels) { 894 HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 895 896 // If this distribution does not set the experiment labels, don't bother 897 // reading. 898 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 899 if (!dist->ShouldSetExperimentLabels()) 900 return false; 901 902 base::string16 client_state_path( 903 system_install ? dist->GetStateMediumKey() : dist->GetStateKey()); 904 905 RegKey client_state; 906 LONG result = client_state.Open( 907 reg_root, client_state_path.c_str(), KEY_QUERY_VALUE | KEY_WOW64_32KEY); 908 if (result == ERROR_SUCCESS) { 909 result = client_state.ReadValue(google_update::kExperimentLabels, 910 experiment_labels); 911 } 912 913 // If the key or value was not present, return the empty string. 914 if (result == ERROR_FILE_NOT_FOUND || result == ERROR_PATH_NOT_FOUND) { 915 experiment_labels->clear(); 916 return true; 917 } 918 919 return result == ERROR_SUCCESS; 920} 921