// 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 "chrome/browser/chromeos/system/statistics_provider.h"

#include "base/bind.h"
#include "base/chromeos/chromeos_version.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/path_service.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "chromeos/app_mode/kiosk_oem_manifest_parser.h"
#include "chromeos/chromeos_constants.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/system/name_value_pairs_parser.h"
#include "content/public/browser/browser_thread.h"

#if defined(GOOGLE_CHROME_BUILD)
// TODO(phajdan.jr): Drop that dependency, http://crbug.com/180711 .
#include "chrome/common/chrome_version_info.h"
#endif

using content::BrowserThread;

namespace chromeos {
namespace system {
namespace {

// Path to the tool used to get system info, and delimiters for the output
// format of the tool.
const char* kCrosSystemTool[] = { "/usr/bin/crossystem" };
const char kCrosSystemEq[] = "=";
const char kCrosSystemDelim[] = "\n";
const char kCrosSystemCommentDelim[] = "#";
const char kCrosSystemUnknownValue[] = "(error)";

const char kHardwareClassCrosSystemKey[] = "hwid";
const char kHardwareClassKey[] = "hardware_class";
const char kUnknownHardwareClass[] = "unknown";

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

// File to get ECHO coupon info from, and key/value delimiters of
// the file.
const char kEchoCouponFile[] = "/var/cache/echo/vpd_echo.txt";
const char kEchoCouponEq[] = "=";
const char kEchoCouponDelim[] = "\n";

// File to get machine OS info from, and key/value delimiters of the file.
const char kMachineOSInfoFile[] = "/etc/lsb-release";
const char kMachineOSInfoEq[] = "=";
const char kMachineOSInfoDelim[] = "\n";

// File to get VPD info from, and key/value delimiters of the file.
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;

// The location of OEM manifest file used to trigger OOBE flow for kiosk mode.
const CommandLine::CharType kOemManifestFilePath[] =
    FILE_PATH_LITERAL("/usr/share/oem/oobe/manifest.json");

}  // namespace

// Key values for GetMachineStatistic()/GetMachineFlag() calls.
const char kDevSwitchBootMode[] = "devsw_boot";
const char kHardwareClass[] = "hardware_class";
const char kMachineInfoBoard[] =
    "CHROMEOS_RELEASE_BOARD";
const char kOffersCouponCodeKey[] = "ubind_attribute";
const char kOffersGroupCodeKey[] = "gbind_attribute";
const char kOemCanExitEnterpriseEnrollmentKey[] =
    "oem_can_exit_enrollment";
const char kOemDeviceRequisitionKey[] =
    "oem_device_requisition";
const char kOemIsEnterpriseManagedKey[] =
    "oem_enterprise_managed";
const char kOemKeyboardDrivenOobeKey[] =
    "oem_keyboard_driven_oobe";

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

  static StatisticsProviderImpl* GetInstance();

 protected:
  StatisticsProviderImpl();
  void LoadOemManifestFromFile(const base::FilePath& file);

 private:
  typedef std::map<std::string, bool> MachineFlags;
  friend struct DefaultSingletonTraits<StatisticsProviderImpl>;

  // Loads the machine info file, which is necessary to get the Chrome channel.
  // Treat MachineOSInfoFile specially, as distribution channel information
  // (stable, beta, dev, canary) is required at earlier stage than everything
  // else. Rather than posting a delayed task, read and parse the machine OS
  // info file immediately.
  void LoadMachineOSInfoFile();

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

  bool initialized_;
  bool load_statistics_started_;
  NameValuePairsParser::NameValueMap machine_info_;
  MachineFlags machine_flags_;
  base::WaitableEvent on_statistics_loaded_;

  DISALLOW_COPY_AND_ASSIGN(StatisticsProviderImpl);
};

void StatisticsProviderImpl::Init() {
  DCHECK(!initialized_);
  initialized_ = true;

  // Load the machine info file immediately to get the channel info.
  LoadMachineOSInfoFile();
}

bool StatisticsProviderImpl::GetMachineStatistic(
    const std::string& name, std::string* result) {
  DCHECK(initialized_);
  DCHECK(load_statistics_started_);

  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;
    // http://crbug.com/125385
    base::ThreadRestrictions::ScopedAllowWait allow_wait;
    on_statistics_loaded_.TimedWait(base::TimeDelta::FromSeconds(kTimeoutSecs));

    if (!on_statistics_loaded_.IsSignaled()) {
      LOG(ERROR) << "Statistics weren't loaded after waiting! "
                 << "Requested statistic: " << name;
      return false;
    }
  }

  NameValuePairsParser::NameValueMap::iterator iter = machine_info_.find(name);
  if (iter != machine_info_.end()) {
    *result = iter->second;
    return true;
  }
  return false;
}

bool StatisticsProviderImpl::GetMachineFlag(
    const std::string& name, bool* result) {
  MachineFlags::const_iterator iter = machine_flags_.find(name);
  if (iter != machine_flags_.end()) {
    *result = iter->second;
    return true;
  }

  return false;
}

void StatisticsProviderImpl::LoadOemManifest() {
  LoadOemManifestFromFile(base::FilePath(kOemManifestFilePath));
}

// manual_reset needs to be true, as we want to keep the signaled state.
StatisticsProviderImpl::StatisticsProviderImpl()
    : initialized_(false),
      load_statistics_started_(false),
      on_statistics_loaded_(true  /* manual_reset */,
                            false /* initially_signaled */) {
}

void StatisticsProviderImpl::LoadMachineOSInfoFile() {
  NameValuePairsParser parser(&machine_info_);
  if (parser.GetNameValuePairsFromFile(base::FilePath(kMachineOSInfoFile),
                                       kMachineOSInfoEq,
                                       kMachineOSInfoDelim)) {
#if defined(GOOGLE_CHROME_BUILD)
    const char kChromeOSReleaseTrack[] = "CHROMEOS_RELEASE_TRACK";
    NameValuePairsParser::NameValueMap::iterator iter =
        machine_info_.find(kChromeOSReleaseTrack);
    if (iter != machine_info_.end())
      chrome::VersionInfo::SetChannel(iter->second);
#endif
  }
}

void StatisticsProviderImpl::StartLoadingMachineStatistics() {
  DCHECK(initialized_);
  DCHECK(!load_statistics_started_);
  load_statistics_started_ = true;

  VLOG(1) << "Started loading statistics";
  BrowserThread::PostBlockingPoolTask(
      FROM_HERE,
      base::Bind(&StatisticsProviderImpl::LoadMachineStatistics,
                 base::Unretained(this)));
}

void StatisticsProviderImpl::LoadMachineStatistics() {
  NameValuePairsParser parser(&machine_info_);

  // Parse all of the key/value pairs from the crossystem tool.
  if (!parser.ParseNameValuePairsFromTool(
          arraysize(kCrosSystemTool), kCrosSystemTool, kCrosSystemEq,
          kCrosSystemDelim, kCrosSystemCommentDelim)) {
    LOG(WARNING) << "There were errors parsing the output of "
                 << kCrosSystemTool << ".";
  }

  // Ensure that the hardware class key is present with the expected
  // key name, and if it couldn't be retrieved, that the value is "unknown".
  std::string hardware_class = machine_info_[kHardwareClassCrosSystemKey];
  if (hardware_class.empty() || hardware_class == kCrosSystemUnknownValue)
    machine_info_[kHardwareClassKey] = kUnknownHardwareClass;
  else
    machine_info_[kHardwareClassKey] = hardware_class;

  parser.GetNameValuePairsFromFile(base::FilePath(kMachineHardwareInfoFile),
                                   kMachineHardwareInfoEq,
                                   kMachineHardwareInfoDelim);
  parser.GetNameValuePairsFromFile(base::FilePath(kEchoCouponFile),
                                   kEchoCouponEq,
                                   kEchoCouponDelim);
  parser.GetNameValuePairsFromFile(base::FilePath(kVpdFile), kVpdEq, kVpdDelim);

  // Finished loading the statistics.
  on_statistics_loaded_.Signal();
  VLOG(1) << "Finished loading statistics";
}

void StatisticsProviderImpl::LoadOemManifestFromFile(
    const base::FilePath& file) {
  KioskOemManifestParser::Manifest oem_manifest;
  if (!KioskOemManifestParser::Load(file, &oem_manifest))
    return;

  machine_info_[kOemDeviceRequisitionKey] =
      oem_manifest.device_requisition;
  machine_flags_[kOemIsEnterpriseManagedKey] =
      oem_manifest.enterprise_managed;
  machine_flags_[kOemCanExitEnterpriseEnrollmentKey] =
      oem_manifest.can_exit_enrollment;
  machine_flags_[kOemKeyboardDrivenOobeKey] =
      oem_manifest.keyboard_driven_oobe;
}

StatisticsProviderImpl* StatisticsProviderImpl::GetInstance() {
  return Singleton<StatisticsProviderImpl,
                   DefaultSingletonTraits<StatisticsProviderImpl> >::get();
}

// The stub StatisticsProvider implementation used on Linux desktop.
class StatisticsProviderStubImpl : public StatisticsProviderImpl {
 public:
  // StatisticsProvider implementation:
  virtual void Init() OVERRIDE {}

  virtual void StartLoadingMachineStatistics() OVERRIDE {}

  virtual bool GetMachineStatistic(const std::string& name,
                                   std::string* result) OVERRIDE {
    if (name == "CHROMEOS_RELEASE_BOARD") {
      // Note: syncer::GetSessionNameSynchronously() also uses the mechanism
      // below to determine the CrOs release board. However, it cannot include
      // statistics_provider.h and use this method because of the mutual
      // dependency that creates between sync.gyp:sync and chrome.gyp:browser.
      // TODO(rsimha): Update syncer::GetSessionNameSynchronously() if this code
      // is ever moved into base/. See http://crbug.com/126732.
      const CommandLine* command_line = CommandLine::ForCurrentProcess();
      if (command_line->HasSwitch(chromeos::switches::kChromeOSReleaseBoard)) {
        *result = command_line->
            GetSwitchValueASCII(chromeos::switches::kChromeOSReleaseBoard);
        return true;
      }
    }
    return false;
  }

  virtual void LoadOemManifest() OVERRIDE {
    CommandLine* command_line = CommandLine::ForCurrentProcess();
    if (!command_line->HasSwitch(switches::kAppOemManifestFile))
      return;

    LoadOemManifestFromFile(
        command_line->GetSwitchValuePath(switches::kAppOemManifestFile));
  }

  static StatisticsProviderStubImpl* GetInstance() {
    return Singleton<StatisticsProviderStubImpl,
        DefaultSingletonTraits<StatisticsProviderStubImpl> >::get();
  }

 private:
  friend struct DefaultSingletonTraits<StatisticsProviderStubImpl>;

  StatisticsProviderStubImpl() {
  }

  DISALLOW_COPY_AND_ASSIGN(StatisticsProviderStubImpl);
};

StatisticsProvider* StatisticsProvider::GetInstance() {
  if (base::chromeos::IsRunningOnChromeOS()) {
    return StatisticsProviderImpl::GetInstance();
  } else {
    return StatisticsProviderStubImpl::GetInstance();
  }
}

}  // namespace system
}  // namespace chromeos
