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

#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/metrics/variations/variations_util.h"
#include "chrome/installer/util/google_update_settings.h"
#include "gpu/config/gpu_info.h"
#include "url/gurl.h"

namespace child_process_logging {

// Account for the terminating null character.
static const size_t kClientIdSize = 32 + 1;
static const size_t kChannelSize = 32;

// We use static strings to hold the most recent active url and the client
// identifier. If we crash, the crash handler code will send the contents of
// these strings to the browser.
char g_client_id[kClientIdSize];

char g_channel[kChannelSize] = "";

static const size_t kGpuStringSize = 32;
char g_gpu_vendor_id[kGpuStringSize] = "";
char g_gpu_device_id[kGpuStringSize] = "";
char g_gpu_gl_vendor[kGpuStringSize] = "";
char g_gpu_gl_renderer[kGpuStringSize] = "";
char g_gpu_driver_ver[kGpuStringSize] = "";
char g_gpu_ps_ver[kGpuStringSize] = "";
char g_gpu_vs_ver[kGpuStringSize] = "";

char g_printer_info[kPrinterInfoStrLen * kMaxReportedPrinterRecords + 1] = "";

static const size_t kNumSize = 32;
char g_num_extensions[kNumSize] = "";
char g_num_switches[kNumSize] = "";
char g_num_variations[kNumSize] = "";
char g_num_views[kNumSize] = "";

static const size_t kMaxExtensionSize =
    kExtensionLen * kMaxReportedActiveExtensions + 1;
char g_extension_ids[kMaxExtensionSize] = "";

// Assume command line switches are less than 64 chars.
static const size_t kMaxSwitchesSize = kSwitchLen * kMaxSwitches + 1;
char g_switches[kMaxSwitchesSize] = "";

static const size_t kMaxVariationChunksSize =
    kMaxVariationChunkSize * kMaxReportedVariationChunks + 1;
char g_variation_chunks[kMaxVariationChunksSize] = "";

void SetClientId(const std::string& client_id) {
  std::string str(client_id);
  ReplaceSubstringsAfterOffset(&str, 0, "-", std::string());

  if (str.empty())
    return;

  base::strlcpy(g_client_id, str.c_str(), kClientIdSize);
  std::wstring wstr = ASCIIToWide(str);
  GoogleUpdateSettings::SetMetricsId(wstr);
}

std::string GetClientId() {
  return std::string(g_client_id);
}

void SetActiveExtensions(const std::set<std::string>& extension_ids) {
  snprintf(g_num_extensions, arraysize(g_num_extensions), "%" PRIuS,
           extension_ids.size());

  std::string extension_str;
  std::set<std::string>::const_iterator iter = extension_ids.begin();
  for (size_t i = 0;
       i < kMaxReportedActiveExtensions && iter != extension_ids.end();
       ++i, ++iter) {
    extension_str += *iter;
  }
  base::strlcpy(g_extension_ids, extension_str.c_str(),
                arraysize(g_extension_ids));
}

void SetGpuInfo(const gpu::GPUInfo& gpu_info) {
  snprintf(g_gpu_vendor_id, arraysize(g_gpu_vendor_id), "0x%04x",
           gpu_info.gpu.vendor_id);
  snprintf(g_gpu_device_id, arraysize(g_gpu_device_id), "0x%04x",
           gpu_info.gpu.device_id);
  base::strlcpy(g_gpu_gl_vendor, gpu_info.gl_vendor.c_str(),
                arraysize(g_gpu_gl_vendor));
  base::strlcpy(g_gpu_gl_renderer, gpu_info.gl_renderer.c_str(),
                arraysize(g_gpu_gl_renderer));
  base::strlcpy(g_gpu_driver_ver, gpu_info.driver_version.c_str(),
                arraysize(g_gpu_driver_ver));
  base::strlcpy(g_gpu_ps_ver, gpu_info.pixel_shader_version.c_str(),
                arraysize(g_gpu_ps_ver));
  base::strlcpy(g_gpu_vs_ver,  gpu_info.vertex_shader_version.c_str(),
                arraysize(g_gpu_vs_ver));
}

void SetPrinterInfo(const char* printer_info) {
  std::string printer_info_str;
  std::vector<std::string> info;
  base::SplitString(printer_info, L';', &info);
  DCHECK_LE(info.size(), kMaxReportedPrinterRecords);
  for (size_t i = 0; i < info.size(); ++i) {
    printer_info_str += info[i];
    // Truncate long switches, align short ones with spaces to be trimmed later.
    printer_info_str.resize((i + 1) * kPrinterInfoStrLen, ' ');
  }
  base::strlcpy(g_printer_info, printer_info_str.c_str(),
                arraysize(g_printer_info));
}

void SetNumberOfViews(int number_of_views) {
  snprintf(g_num_views, arraysize(g_num_views), "%d", number_of_views);
}

void SetCommandLine(const CommandLine* command_line) {
  const CommandLine::StringVector& argv = command_line->argv();

  snprintf(g_num_switches, arraysize(g_num_switches), "%" PRIuS,
           argv.size() - 1);

  std::string command_line_str;
  for (size_t argv_i = 1;
       argv_i < argv.size() && argv_i <= kMaxSwitches;
       ++argv_i) {
    command_line_str += argv[argv_i];
    // Truncate long switches, align short ones with spaces to be trimmed later.
    command_line_str.resize(argv_i * kSwitchLen, ' ');
  }
  base::strlcpy(g_switches, command_line_str.c_str(), arraysize(g_switches));
}

void SetExperimentList(const std::vector<string16>& experiments) {
  std::vector<string16> chunks;
  chrome_variations::GenerateVariationChunks(experiments, &chunks);

  // Store up to |kMaxReportedVariationChunks| chunks.
  std::string chunks_str;
  const size_t number_of_chunks_to_report =
      std::min(chunks.size(), kMaxReportedVariationChunks);
  for (size_t i = 0; i < number_of_chunks_to_report; ++i) {
    chunks_str += UTF16ToUTF8(chunks[i]);
    // Align short chunks with spaces to be trimmed later.
    chunks_str.resize(i * kMaxVariationChunkSize, ' ');
  }
  base::strlcpy(g_variation_chunks, chunks_str.c_str(),
                arraysize(g_variation_chunks));

  // Make note of the total number of experiments, which may be greater than
  // what was able to fit in |kMaxReportedVariationChunks|. This is useful when
  // correlating stability with the number of experiments running
  // simultaneously.
  snprintf(g_num_variations, arraysize(g_num_variations), "%" PRIuS,
           experiments.size());
}

void SetChannel(const std::string& channel) {
  base::strlcpy(g_channel, channel.c_str(), arraysize(g_channel));
}

}  // namespace child_process_logging
