<commit_before>// Copyright (c) 2011 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 "chrome/browser/chromeos/system/statistics_provider.h"

#include "base/bind.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/synchronization/waitable_event.h"
#include "base/task.h"
#include "chrome/browser/chromeos/system/name_value_pairs_parser.h"
#include "chrome/browser/chromeos/system/runtime_environment.h"
#include "content/browser/browser_thread.h"

namespace chromeos {
namespace system {
namespace {

// The tools used here should be specified as absolute paths. The
// existence of the tools is checked in GetSingleValueFromTool().

// The system command that returns the hardware class.
const char kHardwareClassKey[] = "hardware_class";
const char* kHardwareClassTool[] = { "/usr/bin/crossystem", "hwid" };
const char kUnknownHardwareClass[] = "unknown";

// Command to get machine hardware info and key/value delimiters.
// /tmp/machine-info is generated by platform/init/chromeos_startup.
const char kMachineHardwareInfoFile[] = "/tmp/machine-info";
const char kMachineHardwareInfoEq[] = "=";
const char kMachineHardwareInfoDelim[] = " \n";

// Command to get machine OS info and key/value delimiters.
const char kMachineOSInfoFile[] = "/etc/lsb-release";
const char kMachineOSInfoEq[] = "=";
const char kMachineOSInfoDelim[] = "\n";

// Command to get VPD info and key/value delimiters.
const char kVpdFile[] = "/var/log/vpd_2.0.txt";
const char kVpdEq[] = "=";
const char kVpdDelim[] = "\n";

// Gets name-value paris from the file using the parser.
void GetNameValuePairsFromFile(NameValuePairsParser* parser,
                               const FilePath& file_path,
                               const std::string& eq,
                               const std::string& delim) {
  std::string contents;
  if (file_util::ReadFileToString(file_path, &contents)) {
    parser->ParseNameValuePairs(contents, eq, delim);
  }
}

}  // namespace

// The StatisticsProvider implementation used in production.
class StatisticsProviderImpl : public StatisticsProvider {
 public:
  // StatisticsProvider implementation:
  virtual bool GetMachineStatistic(const std::string& name,
                                   std::string* result);

  static StatisticsProviderImpl* GetInstance();

 private:
  friend struct DefaultSingletonTraits<StatisticsProviderImpl>;

  StatisticsProviderImpl();

  // Starts loading the machine statistcs.
  void StartLoadingMachineStatistics();

  // Loads the machine statistcs by examining the system.
  void LoadMachineStatistics();

  NameValuePairsParser::NameValueMap machine_info_;
  base::WaitableEvent on_statistics_loaded_;

  DISALLOW_COPY_AND_ASSIGN(StatisticsProviderImpl);
};

bool StatisticsProviderImpl::GetMachineStatistic(
    const std::string& name, std::string* result) {
  VLOG(1) << "Statistic is requested for " << name;
  // Block if the statistics are not loaded yet. Per LOG(WARNING) below,
  // the statistics are loaded before requested as of now. For regular
  // sessions (i.e. not OOBE), statistics are first requested when the
  // user is logging in.
  //
  // If you see the warning appeared, it probably means that there is
  // new client code that uses the statistics in the very early stage of
  // the browser startup. The statistic name should be helpful to identify
  // the caller.
  if (!on_statistics_loaded_.IsSignaled()) {
    LOG(WARNING) << "Waiting to load statistics. Requested statistic: "
                 << name;
    on_statistics_loaded_.Wait();
  }

  NameValuePairsParser::NameValueMap::iterator iter = machine_info_.find(name);
  if (iter != machine_info_.end()) {
    *result = iter->second;
    return true;<commit_msg>Fix EnterpriseMetricsTest.*<commit_after>// Copyright (c) 2011 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 "chrome/browser/chromeos/system/statistics_provider.h"

#include "base/bind.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/synchronization/waitable_event.h"
#include "base/task.h"
#include "base/time.h"
#include "chrome/browser/chromeos/system/name_value_pairs_parser.h"
#include "chrome/browser/chromeos/system/runtime_environment.h"
#include "content/browser/browser_thread.h"

namespace chromeos {
namespace system {
namespace {

// The tools used here should be specified as absolute paths. The
// existence of the tools is checked in GetSingleValueFromTool().

// The system command that returns the hardware class.
const char kHardwareClassKey[] = "hardware_class";
const char* kHardwareClassTool[] = { "/usr/bin/crossystem", "hwid" };
const char kUnknownHardwareClass[] = "unknown";

// Command to get machine hardware info and key/value delimiters.
// /tmp/machine-info is generated by platform/init/chromeos_startup.
const char kMachineHardwareInfoFile[] = "/tmp/machine-info";
const char kMachineHardwareInfoEq[] = "=";
const char kMachineHardwareInfoDelim[] = " \n";

// Command to get machine OS info and key/value delimiters.
const char kMachineOSInfoFile[] = "/etc/lsb-release";
const char kMachineOSInfoEq[] = "=";
const char kMachineOSInfoDelim[] = "\n";

// Command to get VPD info and key/value delimiters.
const char kVpdFile[] = "/var/log/vpd_2.0.txt";
const char kVpdEq[] = "=";
const char kVpdDelim[] = "\n";

// Timeout that we should wait for statistics to get loaded
const int kTimeoutSecs = 3;

// Gets name-value paris from the file using the parser.
void GetNameValuePairsFromFile(NameValuePairsParser* parser,
                               const FilePath& file_path,
                               const std::string& eq,
                               const std::string& delim) {
  std::string contents;
  if (file_util::ReadFileToString(file_path, &contents)) {
    parser->ParseNameValuePairs(contents, eq, delim);
  }
}

}  // namespace

// The StatisticsProvider implementation used in production.
class StatisticsProviderImpl : public StatisticsProvider {
 public:
  // StatisticsProvider implementation:
  virtual bool GetMachineStatistic(const std::string& name,
                                   std::string* result);

  static StatisticsProviderImpl* GetInstance();

 private:
  friend struct DefaultSingletonTraits<StatisticsProviderImpl>;

  StatisticsProviderImpl();

  // Starts loading the machine statistcs.
  void StartLoadingMachineStatistics();

  // Loads the machine statistcs by examining the system.
  void LoadMachineStatistics();

  NameValuePairsParser::NameValueMap machine_info_;
  base::WaitableEvent on_statistics_loaded_;

  DISALLOW_COPY_AND_ASSIGN(StatisticsProviderImpl);
};

bool StatisticsProviderImpl::GetMachineStatistic(
    const std::string& name, std::string* result) {
  VLOG(1) << "Statistic is requested for " << name;
  // Block if the statistics are not loaded yet. Per LOG(WARNING) below,
  // the statistics are loaded before requested as of now. For regular
  // sessions (i.e. not OOBE), statistics are first requested when the
  // user is logging in so we have plenty of time to load the data
  // beforehand.
  //
  // If you see the warning appeared for regular sessions, it probably
  // means that there is new client code that uses the statistics in the
  // very early stage of the browser startup. The statistic name should be
  // helpful to identify the caller.
  if (!on_statistics_loaded_.IsSignaled()) {
    LOG(WARNING) << "Waiting to load statistics. Requested statistic: "
                 << name;
    on_statistics_loaded_.TimedWait(base::TimeDelta::FromSeconds(kTimeoutSecs));
  }

  NameValuePairsParser::NameValueMap::iterator iter = machine_info_.find(name);
  if (iter != machine_info_.end()) {
    *result = iter->second;
    return true;
{'fraction_non_alphanumeric': 0.10371382436964352, 'fraction_numerical': 0.0018631225934666502, 'mean_word_length': 3.882959369314736, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5320681', 'n_tokens_mistral': 2313, 'n_tokens_neox': 2267, 'n_words': 726}