Home | History | Annotate | Download | only in util
      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