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