// 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/external_metrics.h"

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <map>
#include <string>

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "base/posix/eintr_wrapper.h"
#include "base/sys_info.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/user_metrics.h"

using base::UserMetricsAction;
using content::BrowserThread;

namespace chromeos {

namespace {

bool CheckValues(const std::string& name,
                 int minimum,
                 int maximum,
                 size_t bucket_count) {
  if (!base::Histogram::InspectConstructionArguments(
      name, &minimum, &maximum, &bucket_count))
    return false;
  base::HistogramBase* histogram =
      base::StatisticsRecorder::FindHistogram(name);
  if (!histogram)
    return true;
  return histogram->HasConstructionArguments(minimum, maximum, bucket_count);
}

bool CheckLinearValues(const std::string& name, int maximum) {
  return CheckValues(name, 1, maximum, maximum + 1);
}

// Establishes field trial for wifi scanning in chromeos.  crbug.com/242733.
void SetupProgressiveScanFieldTrial() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  const char name_of_experiment[] = "ProgressiveScan";
  const base::FilePath group_file_path(
      "/home/chronos/.progressive_scan_variation");
  const base::FieldTrial::Probability kDivisor = 1000;
  scoped_refptr<base::FieldTrial> trial =
      base::FieldTrialList::FactoryGetFieldTrial(
          name_of_experiment, kDivisor, "Default", 2013, 12, 31,
          base::FieldTrial::SESSION_RANDOMIZED, NULL);

  // Announce the groups with 0 percentage; the actual percentages come from
  // the server configuration.
  std::map<int, std::string> group_to_char;
  group_to_char[trial->AppendGroup("FullScan", 0)] = "c";
  group_to_char[trial->AppendGroup("33Percent_4MinMax", 0)] = "1";
  group_to_char[trial->AppendGroup("50Percent_4MinMax", 0)] = "2";
  group_to_char[trial->AppendGroup("50Percent_8MinMax", 0)] = "3";
  group_to_char[trial->AppendGroup("100Percent_8MinMax", 0)] = "4";
  group_to_char[trial->AppendGroup("100Percent_1MinSeen_A", 0)] = "5";
  group_to_char[trial->AppendGroup("100Percent_1MinSeen_B", 0)] = "6";
  group_to_char[trial->AppendGroup("100Percent_1Min_4Max", 0)] = "7";

  // Announce the experiment to any listeners (especially important is the UMA
  // software, which will append the group names to UMA statistics).
  const int group_num = trial->group();
  std::string group_char = "x";
  if (ContainsKey(group_to_char, group_num))
    group_char = group_to_char[group_num];

  // Write the group to the file to be read by ChromeOS.
  int size = static_cast<int>(group_char.length());
  if (file_util::WriteFile(group_file_path, group_char.c_str(), size) == size) {
    VLOG(1) << "Configured in group '" << trial->group_name()
            << "' ('" << group_char << "') for "
            << name_of_experiment << " field trial";
  } else {
    LOG(ERROR) << "Couldn't write to " << group_file_path.value();
  }
}

}  // namespace

// The interval between external metrics collections in seconds
static const int kExternalMetricsCollectionIntervalSeconds = 30;

ExternalMetrics::ExternalMetrics() : test_recorder_(NULL) {}

ExternalMetrics::~ExternalMetrics() {}

void ExternalMetrics::Start() {
  // Register user actions external to the browser.
  // tools/metrics/actions/extract_actions.py won't understand these lines, so
  // all of these are explicitly added in that script.
  // TODO(derat): We shouldn't need to verify actions before reporting them;
  // remove all of this once http://crosbug.com/11125 is fixed.
  valid_user_actions_.insert("Cryptohome.PKCS11InitFail");
  valid_user_actions_.insert("Updater.ServerCertificateChanged");
  valid_user_actions_.insert("Updater.ServerCertificateFailed");

  // Initialize here field trials that don't need to read from files.
  // (None for the moment.)

  // Initialize any chromeos field trials that need to read from a file (e.g.,
  // those that have an upstart script determine their experimental group for
  // them) then schedule the data collection.  All of this is done on the file
  // thread.
  bool task_posted = BrowserThread::PostTask(
      BrowserThread::FILE,
      FROM_HERE,
      base::Bind(&chromeos::ExternalMetrics::SetupFieldTrialsOnFileThread,
                 this));
  DCHECK(task_posted);
}

void ExternalMetrics::RecordActionUI(std::string action_string) {
  if (valid_user_actions_.count(action_string)) {
    content::RecordComputedAction(action_string);
  } else {
    DLOG(ERROR) << "undefined UMA action: " << action_string;
  }
}

void ExternalMetrics::RecordAction(const char* action) {
  std::string action_string(action);
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&ExternalMetrics::RecordActionUI, this, action_string));
}

void ExternalMetrics::RecordCrashUI(const std::string& crash_kind) {
  if (g_browser_process && g_browser_process->metrics_service()) {
    g_browser_process->metrics_service()->LogChromeOSCrash(crash_kind);
  }
}

void ExternalMetrics::RecordCrash(const std::string& crash_kind) {
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&ExternalMetrics::RecordCrashUI, this, crash_kind));
}

void ExternalMetrics::RecordHistogram(const char* histogram_data) {
  int sample, min, max, nbuckets;
  char name[128];   // length must be consistent with sscanf format below.
  int n = sscanf(histogram_data, "%127s %d %d %d %d",
                 name, &sample, &min, &max, &nbuckets);
  if (n != 5) {
    DLOG(ERROR) << "bad histogram request: " << histogram_data;
    return;
  }

  if (!CheckValues(name, min, max, nbuckets)) {
    DLOG(ERROR) << "Invalid histogram " << name
                << ", min=" << min
                << ", max=" << max
                << ", nbuckets=" << nbuckets;
    return;
  }
  // Do not use the UMA_HISTOGRAM_... macros here.  They cache the Histogram
  // instance and thus only work if |name| is constant.
  base::HistogramBase* counter = base::Histogram::FactoryGet(
      name, min, max, nbuckets, base::Histogram::kUmaTargetedHistogramFlag);
  counter->Add(sample);
}

void ExternalMetrics::RecordLinearHistogram(const char* histogram_data) {
  int sample, max;
  char name[128];   // length must be consistent with sscanf format below.
  int n = sscanf(histogram_data, "%127s %d %d", name, &sample, &max);
  if (n != 3) {
    DLOG(ERROR) << "bad linear histogram request: " << histogram_data;
    return;
  }

  if (!CheckLinearValues(name, max)) {
    DLOG(ERROR) << "Invalid linear histogram " << name
                << ", max=" << max;
    return;
  }
  // Do not use the UMA_HISTOGRAM_... macros here.  They cache the Histogram
  // instance and thus only work if |name| is constant.
  base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
      name, 1, max, max + 1, base::Histogram::kUmaTargetedHistogramFlag);
  counter->Add(sample);
}

void ExternalMetrics::RecordSparseHistogram(const char* histogram_data) {
  int sample;
  char name[128];   // length must be consistent with sscanf format below.
  int n = sscanf(histogram_data, "%127s %d", name, &sample);
  if (n != 2) {
    DLOG(ERROR) << "bad sparse histogram request: " << histogram_data;
    return;
  }

  // Do not use the UMA_HISTOGRAM_... macros here.  They cache the Histogram
  // instance and thus only work if |name| is constant.
  base::HistogramBase* counter = base::SparseHistogram::FactoryGet(
      name, base::HistogramBase::kUmaTargetedHistogramFlag);
  counter->Add(sample);
}

void ExternalMetrics::CollectEvents() {
  const char* event_file_path = "/var/log/metrics/uma-events";
  struct stat stat_buf;
  int result;
  if (!test_path_.empty()) {
    event_file_path = test_path_.value().c_str();
  }
  result = stat(event_file_path, &stat_buf);
  if (result < 0) {
    if (errno != ENOENT) {
      DPLOG(ERROR) << event_file_path << ": bad metrics file stat";
    }
    // Nothing to collect---try later.
    return;
  }
  if (stat_buf.st_size == 0) {
    // Also nothing to collect.
    return;
  }
  int fd = open(event_file_path, O_RDWR);
  if (fd < 0) {
    DPLOG(ERROR) << event_file_path << ": cannot open";
    return;
  }
  result = flock(fd, LOCK_EX);
  if (result < 0) {
    DPLOG(ERROR) << event_file_path << ": cannot lock";
    close(fd);
    return;
  }
  // This processes all messages in the log.  Each message starts with a 4-byte
  // field containing the length of the entire message.  The length is followed
  // by a name-value pair of null-terminated strings.  When all messages are
  // read and processed, or an error occurs, truncate the file to zero size.
  for (;;) {
    int32 message_size;
    result = HANDLE_EINTR(read(fd, &message_size, sizeof(message_size)));
    if (result < 0) {
      DPLOG(ERROR) << "reading metrics message header";
      break;
    }
    if (result == 0) {  // This indicates a normal EOF.
      break;
    }
    if (result < static_cast<int>(sizeof(message_size))) {
      DLOG(ERROR) << "bad read size " << result <<
                     ", expecting " << sizeof(message_size);
      break;
    }
    // kMetricsMessageMaxLength applies to the entire message: the 4-byte
    // length field and the two null-terminated strings.
    if (message_size < 2 + static_cast<int>(sizeof(message_size)) ||
        message_size > static_cast<int>(kMetricsMessageMaxLength)) {
      DLOG(ERROR) << "bad message size " << message_size;
      break;
    }
    message_size -= sizeof(message_size);  // The message size includes itself.
    uint8 buffer[kMetricsMessageMaxLength];
    result = HANDLE_EINTR(read(fd, buffer, message_size));
    if (result < 0) {
      DPLOG(ERROR) << "reading metrics message body";
      break;
    }
    if (result < message_size) {
      DLOG(ERROR) << "message too short: length " << result <<
                     ", expected " << message_size;
      break;
    }
    // The buffer should now contain a pair of null-terminated strings.
    uint8* p = reinterpret_cast<uint8*>(memchr(buffer, '\0', message_size));
    uint8* q = NULL;
    if (p != NULL) {
      q = reinterpret_cast<uint8*>(
          memchr(p + 1, '\0', message_size - (p + 1 - buffer)));
    }
    if (q == NULL) {
      DLOG(ERROR) << "bad name-value pair for metrics";
      break;
    }
    char* name = reinterpret_cast<char*>(buffer);
    char* value = reinterpret_cast<char*>(p + 1);
    if (test_recorder_ != NULL) {
      test_recorder_(name, value);
    } else if (strcmp(name, "crash") == 0) {
      RecordCrash(value);
    } else if (strcmp(name, "histogram") == 0) {
      RecordHistogram(value);
    } else if (strcmp(name, "linearhistogram") == 0) {
      RecordLinearHistogram(value);
    } else if (strcmp(name, "sparsehistogram") == 0) {
      RecordSparseHistogram(value);
    } else if (strcmp(name, "useraction") == 0) {
      RecordAction(value);
    } else {
      DLOG(ERROR) << "invalid event type: " << name;
    }
  }

  result = ftruncate(fd, 0);
  if (result < 0) {
    DPLOG(ERROR) << "truncate metrics log";
  }
  result = flock(fd, LOCK_UN);
  if (result < 0) {
    DPLOG(ERROR) << "unlock metrics log";
  }
  result = close(fd);
  if (result < 0) {
    DPLOG(ERROR) << "close metrics log";
  }
}

void ExternalMetrics::CollectEventsAndReschedule() {
  base::ElapsedTimer timer;
  CollectEvents();
  UMA_HISTOGRAM_TIMES("UMA.CollectExternalEventsTime", timer.Elapsed());
  ScheduleCollector();
}

void ExternalMetrics::ScheduleCollector() {
  bool result;
  result = BrowserThread::PostDelayedTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&chromeos::ExternalMetrics::CollectEventsAndReschedule, this),
      base::TimeDelta::FromSeconds(kExternalMetricsCollectionIntervalSeconds));
  DCHECK(result);
}

void ExternalMetrics::SetupFieldTrialsOnFileThread() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  // Field trials that do not read from files can be initialized in
  // ExternalMetrics::Start() above.
  SetupProgressiveScanFieldTrial();

  ScheduleCollector();
}

}  // namespace chromeos
