text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "remoting/host/usage_stats_consent.h"
  
  #include <windows.h>
  #include <string>
  
  #include "base/logging.h"
  #include "base/strings/stringprintf.h"
  #include "base/win/registry.h"
  #include "remoting/host/win/omaha.h"
  
  namespace {
  
  // The following strings are used to construct the registry key names where
  // we record whether the user has consented to crash dump collection.
  // the user's consent to collect crash dumps is recorded.
  const wchar_t kOmahaClientStateKeyFormat[] =
      L"Software\\Google\\Update\\%ls\\%ls";
  const wchar_t kOmahaClientState[] = L"ClientState";
  const wchar_t kOmahaClientStateMedium[] = L"ClientStateMedium";
  const wchar_t kOmahaUsagestatsValue[] = L"usagestats";
  
  LONG ReadUsageStatsValue(const wchar_t* state_key, DWORD* usagestats_out) {
    // presubmit: allow wstring
    std::wstring client_state = base::StringPrintf(kOmahaClientStateKeyFormat,
                                                   state_key,
                                                   remoting::kHostOmahaAppid);
    base::win::RegKey key;
    LONG result = key.Open(HKEY_LOCAL_MACHINE, client_state.c_str(), KEY_READ);
    if (result != ERROR_SUCCESS) {
      return result;
    }
  
    return key.ReadValueDW(kOmahaUsagestatsValue, usagestats_out);
  }
  
  }  // namespace
  
  namespace remoting {
  
  bool GetUsageStatsConsent(bool* allowed, bool* set_by_policy) {
    // TODO(alexeypa): report whether the consent is set by policy once
    // supported.
    *set_by_policy = false;
  
    // The user's consent to collect crash dumps is recorded as the "usagestats"
    // value in the ClientState or ClientStateMedium key. Probe the
    // ClientStateMedium key first.
    DWORD value = 0;
    if (ReadUsageStatsValue(kOmahaClientStateMedium, &value) == ERROR_SUCCESS) {
      *allowed = value != 0;
      return true;
    }
    if (ReadUsageStatsValue(kOmahaClientState, &value) == ERROR_SUCCESS) {
      *allowed = value != 0;
      return true;
    }
  
    // We do not log the error code here because the logging hasn't been
    // initialized yet.
    return false;
  }
  
  bool IsUsageStatsAllowed() {
    bool allowed;
    bool set_by_policy;
    return GetUsageStatsConsent(&allowed, &set_by_policy) && allowed;
  }
  
  bool SetUsageStatsConsent(bool allowed) {
    DWORD value = allowed;
    // presubmit: allow wstring
    std::wstring client_state = base::StringPrintf(kOmahaClientStateKeyFormat,
                                                   kOmahaClientStateMedium,
                                                   kHostOmahaAppid);
    base::win::RegKey key;
    LONG result = key.Create(HKEY_LOCAL_MACHINE, client_state.c_str(),
                             KEY_SET_VALUE);
    if (result == ERROR_SUCCESS) {
      result = key.WriteValue(kOmahaUsagestatsValue, value);
      if (result == ERROR_SUCCESS) {
        return true;
      }
    }
  
    PLOG(ERROR) << "Failed to record the user's consent to crash dump reporting";
    return false;
  }
  
  }  // namespace remoting
  