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