// 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.

// A command-line tool that inspects the current system, displaying information
// about installed products.  Violations are dumped to stderr.  The process
// exit code is 0 if there are no violations, or 1 otherwise.

#include <cstdio>
#include <cstdlib>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "chrome/installer/util/installation_validator.h"

using installer::InstallationValidator;

namespace {

// A helper class that initializes logging and installs a log message handler to
// direct ERROR messages to stderr.  Only one instance of this class may be live
// at a time.
class ConsoleLogHelper {
 public:
  ConsoleLogHelper();
  ~ConsoleLogHelper();

 private:
  static base::FilePath GetLogFilePath();
  static bool DumpLogMessage(int severity,
                             const char* file,
                             int line,
                             size_t message_start,
                             const std::string& str);

  static const wchar_t kLogFileName_[];
  static FILE* const kOutputStream_;
  static const logging::LogSeverity kViolationSeverity_;
  static logging::LogMessageHandlerFunction old_message_handler_;
  base::FilePath log_file_path_;
};

// static
const wchar_t ConsoleLogHelper::kLogFileName_[] = L"validate_installation.log";

// Dump violations to stderr.
// static
FILE* const ConsoleLogHelper::kOutputStream_ = stderr;

// InstallationValidator logs all violations at ERROR level.
// static
const logging::LogSeverity
    ConsoleLogHelper::kViolationSeverity_ = logging::LOG_ERROR;

// static
logging::LogMessageHandlerFunction
    ConsoleLogHelper::old_message_handler_ = NULL;

ConsoleLogHelper::ConsoleLogHelper() : log_file_path_(GetLogFilePath()) {
  LOG_ASSERT(old_message_handler_ == NULL);
  logging::LoggingSettings settings;
  settings.logging_dest = logging::LOG_TO_FILE;
  settings.log_file = log_file_path_.value().c_str();
  settings.lock_log = logging::DONT_LOCK_LOG_FILE;
  settings.delete_old = logging::DELETE_OLD_LOG_FILE;
  logging::InitLogging(settings);

  old_message_handler_ = logging::GetLogMessageHandler();
  logging::SetLogMessageHandler(&DumpLogMessage);
}

ConsoleLogHelper::~ConsoleLogHelper() {
  logging::SetLogMessageHandler(old_message_handler_);
  old_message_handler_ = NULL;

  logging::CloseLogFile();

  // Delete the log file if it wasn't written to (this is expected).
  int64 file_size = 0;
  if (base::GetFileSize(log_file_path_, &file_size) && file_size == 0)
    base::DeleteFile(log_file_path_, false);
}

// Returns the path to the log file to create.  The file should be empty at
// process exit since we redirect log messages to stderr.
// static
base::FilePath ConsoleLogHelper::GetLogFilePath() {
  base::FilePath log_path;

  if (PathService::Get(base::DIR_TEMP, &log_path))
    return log_path.Append(kLogFileName_);
  else
    return base::FilePath(kLogFileName_);
}

// A logging::LogMessageHandlerFunction that sends the body of messages logged
// at the severity of validation violations to stderr.  All other messages are
// sent through the default logging pipeline.
// static
bool ConsoleLogHelper::DumpLogMessage(int severity,
                                      const char* file,
                                      int line,
                                      size_t message_start,
                                      const std::string& str) {
  if (severity == kViolationSeverity_) {
    fprintf(kOutputStream_, "%s", str.c_str() + message_start);
    return true;
  }

  if (old_message_handler_ != NULL)
    return (old_message_handler_)(severity, file, line, message_start, str);

  return false;
}

const char* LevelToString(bool system_level) {
  return system_level ? "System-level" : "User-level";
}

std::string InstallationTypeToString(
    InstallationValidator::InstallationType type) {
  std::string result;

  static const struct ProductData {
    int bit;
    const char* name;
  } kProdBitToName[] = {
    {
      InstallationValidator::ProductBits::CHROME_SINGLE,
      "Chrome"
    }, {
      InstallationValidator::ProductBits::CHROME_MULTI,
      "Chrome (multi)"
    }, {
      InstallationValidator::ProductBits::CHROME_FRAME_SINGLE,
      "Chrome Frame"
    }, {
      InstallationValidator::ProductBits::CHROME_FRAME_MULTI,
      "Chrome Frame (multi)"
    }, {
      InstallationValidator::ProductBits::CHROME_FRAME_READY_MODE,
      "Ready-mode Chrome Frame"
    },
  };

  for (size_t i = 0; i < arraysize(kProdBitToName); ++i) {
    const ProductData& product_data = kProdBitToName[i];
    if ((type & product_data.bit) != 0) {
      if (!result.empty())
        result.append(", ");
      result.append(product_data.name);
    }
  }

  return result;
}

}  // namespace

// The main program.
int wmain(int argc, wchar_t *argv[]) {
  int result = EXIT_SUCCESS;
  base::AtExitManager exit_manager;

  base::CommandLine::Init(0, NULL);
  ConsoleLogHelper log_helper;

  // Check user-level and system-level for products.
  for (int i = 0; i < 2; ++i) {
    const bool system_level = (i != 0);
    InstallationValidator::InstallationType type =
        InstallationValidator::NO_PRODUCTS;
    bool is_valid =
        InstallationValidator::ValidateInstallationType(system_level, &type);
    if (type != InstallationValidator::NO_PRODUCTS) {
      FILE* stream = is_valid ? stdout : stderr;
      fprintf(stream, "%s installations%s: %s\n", LevelToString(system_level),
              (is_valid ? "" : " (with errors)"),
              InstallationTypeToString(type).c_str());
    }
    if (!is_valid)
      result = EXIT_FAILURE;
  }

  return result;
}
