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 
      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 
     31 using base::win::RegKey;
     32 using installer::InstallationState;
     33 
     34 const wchar_t GoogleUpdateSettings::kPoliciesKey[] =
     35     L"SOFTWARE\\Policies\\Google\\Update";
     36 const wchar_t GoogleUpdateSettings::kUpdatePolicyValue[] = L"UpdateDefault";
     37 const wchar_t GoogleUpdateSettings::kUpdateOverrideValuePrefix[] = L"Update";
     38 const wchar_t GoogleUpdateSettings::kCheckPeriodOverrideMinutes[] =
     39     L"AutoUpdateCheckPeriodMinutes";
     40 
     41 // Don't allow update periods longer than six weeks.
     42 const int GoogleUpdateSettings::kCheckPeriodOverrideMinutesMax =
     43     60 * 24 * 7 * 6;
     44 
     45 const GoogleUpdateSettings::UpdatePolicy
     46 GoogleUpdateSettings::kDefaultUpdatePolicy =
     47 #if defined(GOOGLE_CHROME_BUILD)
     48     GoogleUpdateSettings::AUTOMATIC_UPDATES;
     49 #else
     50     GoogleUpdateSettings::UPDATES_DISABLED;
     51 #endif
     52 
     53 namespace {
     54 
     55 bool 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.
     71 bool 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 
    101 bool 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 
    108 bool 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 
    120 bool 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 
    131 bool 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|.
    179 bool 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.
    197 bool 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 
    206 bool 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 
    218 bool 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.
    227 bool 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 
    263 bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented) {
    264   return SetCollectStatsConsentAtLevel(IsSystemInstall(), consented);
    265 }
    266 
    267 bool 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 
    299 scoped_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 
    325 void 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.
    339 bool 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 
    378 int 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 
    390 bool GoogleUpdateSettings::SetLastRunTime() {
    391   int64 time = base::Time::NowFromSystemTime().ToInternalValue();
    392   return WriteGoogleUpdateStrKey(google_update::kRegLastRunTimeField,
    393                                  base::Int64ToString16(time));
    394 }
    395 
    396 bool GoogleUpdateSettings::RemoveLastRunTime() {
    397   return RemoveGoogleUpdateStrKey(google_update::kRegLastRunTimeField);
    398 }
    399 
    400 bool GoogleUpdateSettings::GetBrowser(base::string16* browser) {
    401   return ReadGoogleUpdateStrKey(google_update::kRegBrowserField, browser);
    402 }
    403 
    404 bool GoogleUpdateSettings::GetLanguage(base::string16* language) {
    405   return ReadGoogleUpdateStrKey(google_update::kRegLangField, language);
    406 }
    407 
    408 bool GoogleUpdateSettings::GetBrand(base::string16* brand) {
    409   return ReadGoogleUpdateStrKey(google_update::kRegRLZBrandField, brand);
    410 }
    411 
    412 bool GoogleUpdateSettings::GetReactivationBrand(base::string16* brand) {
    413   return ReadGoogleUpdateStrKey(google_update::kRegRLZReactivationBrandField,
    414                                 brand);
    415 }
    416 
    417 bool GoogleUpdateSettings::GetClient(base::string16* client) {
    418   return ReadGoogleUpdateStrKey(google_update::kRegClientField, client);
    419 }
    420 
    421 bool GoogleUpdateSettings::SetClient(const base::string16& client) {
    422   return WriteGoogleUpdateStrKey(google_update::kRegClientField, client);
    423 }
    424 
    425 bool GoogleUpdateSettings::GetReferral(base::string16* referral) {
    426   return ReadGoogleUpdateStrKey(google_update::kRegReferralField, referral);
    427 }
    428 
    429 bool GoogleUpdateSettings::ClearReferral() {
    430   return ClearGoogleUpdateStrKey(google_update::kRegReferralField);
    431 }
    432 
    433 bool 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 
    443 bool 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 
    453 base::string16 GoogleUpdateSettings::GetChromeChannel(bool system_install) {
    454   base::string16 channel;
    455   GetChromeChannelInternal(system_install, false, &channel);
    456   return channel;
    457 }
    458 
    459 bool GoogleUpdateSettings::GetChromeChannelAndModifiers(
    460     bool system_install,
    461     base::string16* channel) {
    462   return GetChromeChannelInternal(system_install, true, channel);
    463 }
    464 
    465 void 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 
    509 bool 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 
    547 void 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 
    563 int 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 
    582 bool 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 
    591 GoogleUpdateSettings::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
    628 bool GoogleUpdateSettings::AreAutoupdatesEnabled() {
    629 #if defined(GOOGLE_CHROME_BUILD)
    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   // Auto updates are subtly broken when Chrome and the binaries have different
    644   // overrides in place. If this Chrome cannot possibly be multi-install by
    645   // virtue of being a side-by-side installation, simply check Chrome's policy.
    646   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
    647   UpdatePolicy app_policy = GetAppUpdatePolicy(dist->GetAppGuid(), nullptr);
    648   if (InstallUtil::IsChromeSxSProcess())
    649     return app_policy == AUTOMATIC_UPDATES || app_policy == AUTO_UPDATES_ONLY;
    650 
    651   // Otherwise, check for consistency between Chrome and the binaries regardless
    652   // of whether or not this Chrome is multi-install since the next update likely
    653   // will attempt to migrate it to such.
    654   BrowserDistribution* binaries = BrowserDistribution::GetSpecificDistribution(
    655       BrowserDistribution::CHROME_BINARIES);
    656   return (GetAppUpdatePolicy(binaries->GetAppGuid(), nullptr) == app_policy &&
    657           (app_policy == AUTOMATIC_UPDATES || app_policy == AUTO_UPDATES_ONLY));
    658 #else  // defined(GOOGLE_CHROME_BUILD)
    659   // Chromium does not auto update.
    660   return false;
    661 #endif  // !defined(GOOGLE_CHROME_BUILD)
    662 }
    663 
    664 // static
    665 bool GoogleUpdateSettings::ReenableAutoupdates() {
    666 #if defined(GOOGLE_CHROME_BUILD)
    667   int needs_reset_count = 0;
    668   int did_reset_count = 0;
    669 
    670   // Reset overrides for Chrome and for the binaries if this Chrome supports
    671   // multi-install.
    672   std::vector<base::string16> app_guids;
    673   app_guids.push_back(BrowserDistribution::GetDistribution()->GetAppGuid());
    674   if (!InstallUtil::IsChromeSxSProcess()) {
    675     app_guids.push_back(BrowserDistribution::GetSpecificDistribution(
    676         BrowserDistribution::CHROME_BINARIES)->GetAppGuid());
    677   }
    678 
    679   UpdatePolicy update_policy = kDefaultUpdatePolicy;
    680   RegKey policy_key;
    681   if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey,
    682                       KEY_SET_VALUE | KEY_QUERY_VALUE) == ERROR_SUCCESS) {
    683     // Set to true while app-specific overrides are present that allow automatic
    684     // updates. When this is the case, the defaults are irrelevant and don't
    685     // need to be checked or reset.
    686     bool automatic_updates_allowed_by_overrides = true;
    687     DWORD value = 0;
    688     for (const base::string16& app_guid : app_guids) {
    689       // First check the app-specific override value and reset that if needed.
    690       // Note that this intentionally sets the override to AUTOMATIC_UPDATES
    691       // even if it was previously AUTO_UPDATES_ONLY. The thinking is that
    692       // AUTOMATIC_UPDATES is marginally more likely to let a user update and
    693       // this code is only called when a stuck user asks for updates.
    694       base::string16 app_update_override(kUpdateOverrideValuePrefix);
    695       app_update_override.append(app_guid);
    696       if (policy_key.ReadValueDW(app_update_override.c_str(),
    697                                  &value) != ERROR_SUCCESS) {
    698         automatic_updates_allowed_by_overrides = false;
    699       } else if (!GetUpdatePolicyFromDword(value, &update_policy) ||
    700                  update_policy != GoogleUpdateSettings::AUTOMATIC_UPDATES) {
    701         automatic_updates_allowed_by_overrides = false;
    702         ++needs_reset_count;
    703         if (policy_key.WriteValue(
    704                 app_update_override.c_str(),
    705                 static_cast<DWORD>(GoogleUpdateSettings::AUTOMATIC_UPDATES)) ==
    706             ERROR_SUCCESS) {
    707           ++did_reset_count;
    708         }
    709       }
    710     }
    711 
    712     // If there were no app-specific override policies, see if there's a global
    713     // policy preventing updates and delete it if so.
    714     if (!automatic_updates_allowed_by_overrides &&
    715         policy_key.ReadValueDW(kUpdatePolicyValue, &value) == ERROR_SUCCESS &&
    716         (!GetUpdatePolicyFromDword(value, &update_policy) ||
    717          update_policy != GoogleUpdateSettings::AUTOMATIC_UPDATES)) {
    718       ++needs_reset_count;
    719       if (policy_key.DeleteValue(kUpdatePolicyValue) == ERROR_SUCCESS)
    720         ++did_reset_count;
    721     }
    722 
    723     // Check the auto-update check period override. If it is 0 or exceeds
    724     // the maximum timeout, delete the override value.
    725     if (policy_key.ReadValueDW(kCheckPeriodOverrideMinutes,
    726                                &value) == ERROR_SUCCESS &&
    727         (value == 0 || value > kCheckPeriodOverrideMinutesMax)) {
    728       ++needs_reset_count;
    729       if (policy_key.DeleteValue(kCheckPeriodOverrideMinutes) == ERROR_SUCCESS)
    730         ++did_reset_count;
    731     }
    732 
    733     // Return whether the number of successful resets is the same as the
    734     // number of things that appeared to need resetting.
    735     return (needs_reset_count == did_reset_count);
    736   } else {
    737     // For some reason we couldn't open the policy key with the desired
    738     // permissions to make changes (the most likely reason is that there is no
    739     // policy set). Simply return whether or not we think updates are enabled.
    740     return AreAutoupdatesEnabled();
    741   }
    742 
    743 #endif
    744   // Non Google Chrome isn't going to autoupdate.
    745   return true;
    746 }
    747 
    748 void GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms() {
    749   const bool is_multi_install = InstallUtil::IsMultiInstall(
    750       BrowserDistribution::GetDistribution(), IsSystemInstall());
    751   const base::string16 app_guid =
    752       BrowserDistribution::GetSpecificDistribution(
    753           is_multi_install ? BrowserDistribution::CHROME_BINARIES :
    754                              BrowserDistribution::CHROME_BROWSER)->GetAppGuid();
    755 
    756   bool is_overridden = false;
    757   const UpdatePolicy update_policy = GetAppUpdatePolicy(app_guid,
    758                                                         &is_overridden);
    759   UMA_HISTOGRAM_BOOLEAN("GoogleUpdate.UpdatePolicyIsOverridden", is_overridden);
    760   UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.EffectivePolicy", update_policy,
    761                             UPDATE_POLICIES_COUNT);
    762 }
    763 
    764 base::string16 GoogleUpdateSettings::GetUninstallCommandLine(
    765     bool system_install) {
    766   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    767   base::string16 cmd_line;
    768   RegKey update_key;
    769 
    770   if (update_key.Open(root_key, google_update::kRegPathGoogleUpdate,
    771                       KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
    772     update_key.ReadValue(google_update::kRegUninstallCmdLine, &cmd_line);
    773   }
    774 
    775   return cmd_line;
    776 }
    777 
    778 Version GoogleUpdateSettings::GetGoogleUpdateVersion(bool system_install) {
    779   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    780   base::string16 version;
    781   RegKey key;
    782 
    783   if (key.Open(root_key,
    784                google_update::kRegPathGoogleUpdate,
    785                KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS &&
    786       key.ReadValue(google_update::kRegGoogleUpdateVersion, &version) ==
    787           ERROR_SUCCESS) {
    788     return Version(base::UTF16ToUTF8(version));
    789   }
    790 
    791   return Version();
    792 }
    793 
    794 base::Time GoogleUpdateSettings::GetGoogleUpdateLastStartedAU(
    795     bool system_install) {
    796   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    797   RegKey update_key;
    798 
    799   if (update_key.Open(root_key,
    800                       google_update::kRegPathGoogleUpdate,
    801                       KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
    802     DWORD last_start;
    803     if (update_key.ReadValueDW(google_update::kRegLastStartedAUField,
    804                                &last_start) == ERROR_SUCCESS) {
    805       return base::Time::FromTimeT(last_start);
    806     }
    807   }
    808 
    809   return base::Time();
    810 }
    811 
    812 base::Time GoogleUpdateSettings::GetGoogleUpdateLastChecked(
    813     bool system_install) {
    814   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    815   RegKey update_key;
    816 
    817   if (update_key.Open(root_key,
    818                       google_update::kRegPathGoogleUpdate,
    819                       KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
    820     DWORD last_check;
    821     if (update_key.ReadValueDW(google_update::kRegLastCheckedField,
    822                                &last_check) == ERROR_SUCCESS) {
    823       return base::Time::FromTimeT(last_check);
    824     }
    825   }
    826 
    827   return base::Time();
    828 }
    829 
    830 bool GoogleUpdateSettings::GetUpdateDetailForApp(bool system_install,
    831                                                  const wchar_t* app_guid,
    832                                                  ProductData* data) {
    833   DCHECK(app_guid);
    834   DCHECK(data);
    835 
    836   bool product_found = false;
    837 
    838   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    839   base::string16 clientstate_reg_path(google_update::kRegPathClientState);
    840   clientstate_reg_path.append(L"\\");
    841   clientstate_reg_path.append(app_guid);
    842 
    843   RegKey clientstate;
    844   if (clientstate.Open(root_key,
    845                        clientstate_reg_path.c_str(),
    846                        KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
    847     base::string16 version;
    848     DWORD dword_value;
    849     if ((clientstate.ReadValueDW(google_update::kRegLastCheckSuccessField,
    850                                  &dword_value) == ERROR_SUCCESS) &&
    851         (clientstate.ReadValue(google_update::kRegVersionField,
    852                                &version) == ERROR_SUCCESS)) {
    853       product_found = true;
    854       data->version = base::UTF16ToASCII(version);
    855       data->last_success = base::Time::FromTimeT(dword_value);
    856       data->last_result = 0;
    857       data->last_error_code = 0;
    858       data->last_extra_code = 0;
    859 
    860       if (clientstate.ReadValueDW(google_update::kRegLastInstallerResultField,
    861                                   &dword_value) == ERROR_SUCCESS) {
    862         // Google Update convention is that if an installer writes an result
    863         // code that is invalid, it is clamped to an exit code result.
    864         const DWORD kMaxValidInstallResult = 4;  // INSTALLER_RESULT_EXIT_CODE
    865         data->last_result = std::min(dword_value, kMaxValidInstallResult);
    866       }
    867       if (clientstate.ReadValueDW(google_update::kRegLastInstallerErrorField,
    868                                   &dword_value) == ERROR_SUCCESS) {
    869         data->last_error_code = dword_value;
    870       }
    871       if (clientstate.ReadValueDW(google_update::kRegLastInstallerExtraField,
    872                                   &dword_value) == ERROR_SUCCESS) {
    873         data->last_extra_code = dword_value;
    874       }
    875     }
    876   }
    877 
    878   return product_found;
    879 }
    880 
    881 bool GoogleUpdateSettings::GetUpdateDetailForGoogleUpdate(bool system_install,
    882                                                           ProductData* data) {
    883   return GetUpdateDetailForApp(system_install,
    884                                google_update::kGoogleUpdateUpgradeCode,
    885                                data);
    886 }
    887 
    888 bool GoogleUpdateSettings::GetUpdateDetail(bool system_install,
    889                                            ProductData* data) {
    890   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
    891   return GetUpdateDetailForApp(system_install,
    892                                dist->GetAppGuid().c_str(),
    893                                data);
    894 }
    895 
    896 bool GoogleUpdateSettings::SetExperimentLabels(
    897     bool system_install,
    898     const base::string16& experiment_labels) {
    899   HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    900 
    901   // Use the browser distribution and install level to write to the correct
    902   // client state/app guid key.
    903   bool success = false;
    904   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
    905   if (dist->ShouldSetExperimentLabels()) {
    906     base::string16 client_state_path(
    907         system_install ? dist->GetStateMediumKey() : dist->GetStateKey());
    908     RegKey client_state(
    909         reg_root, client_state_path.c_str(), KEY_SET_VALUE | KEY_WOW64_32KEY);
    910     if (experiment_labels.empty()) {
    911       success = client_state.DeleteValue(google_update::kExperimentLabels)
    912           == ERROR_SUCCESS;
    913     } else {
    914       success = client_state.WriteValue(google_update::kExperimentLabels,
    915           experiment_labels.c_str()) == ERROR_SUCCESS;
    916     }
    917   }
    918 
    919   return success;
    920 }
    921 
    922 bool GoogleUpdateSettings::ReadExperimentLabels(
    923     bool system_install,
    924     base::string16* experiment_labels) {
    925   HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    926 
    927   // If this distribution does not set the experiment labels, don't bother
    928   // reading.
    929   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
    930   if (!dist->ShouldSetExperimentLabels())
    931     return false;
    932 
    933   base::string16 client_state_path(
    934       system_install ? dist->GetStateMediumKey() : dist->GetStateKey());
    935 
    936   RegKey client_state;
    937   LONG result = client_state.Open(
    938       reg_root, client_state_path.c_str(), KEY_QUERY_VALUE | KEY_WOW64_32KEY);
    939   if (result == ERROR_SUCCESS) {
    940     result = client_state.ReadValue(google_update::kExperimentLabels,
    941                                     experiment_labels);
    942   }
    943 
    944   // If the key or value was not present, return the empty string.
    945   if (result == ERROR_FILE_NOT_FOUND || result == ERROR_PATH_NOT_FOUND) {
    946     experiment_labels->clear();
    947     return true;
    948   }
    949 
    950   return result == ERROR_SUCCESS;
    951 }
    952