// 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 "extensions/browser/warning_set.h"

#include <stddef.h>

#include "base/files/file_path.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/extensions_client.h"
#include "extensions/strings/grit/extensions_strings.h"
#include "net/base/escape.h"
#include "ui/base/l10n/l10n_util.h"

using content::BrowserThread;

namespace {
// Prefix for message parameters indicating that the parameter needs to
// be translated from an extension id to the extension name.
const char kTranslate[] = "TO_TRANSLATE:";
const size_t kMaxNumberOfParameters = 4;
}

namespace extensions {

//
// Warning
//

Warning::Warning(
    WarningType type,
    const std::string& extension_id,
    int message_id,
    const std::vector<std::string>& message_parameters)
    : type_(type),
      extension_id_(extension_id),
      message_id_(message_id),
      message_parameters_(message_parameters) {
  // These are invalid here because they do not have corresponding warning
  // messages in the UI.
  CHECK_NE(type, kInvalid);
  CHECK_NE(type, kMaxWarningType);
  CHECK_LE(message_parameters.size(), kMaxNumberOfParameters);
}

Warning::Warning(const Warning& other)
  : type_(other.type_),
    extension_id_(other.extension_id_),
    message_id_(other.message_id_),
    message_parameters_(other.message_parameters_) {}

Warning::~Warning() {
}

Warning& Warning::operator=(const Warning& other) {
  type_ = other.type_;
  extension_id_ = other.extension_id_;
  message_id_ = other.message_id_;
  message_parameters_ = other.message_parameters_;
  return *this;
}

// static
Warning Warning::CreateNetworkDelayWarning(
    const std::string& extension_id) {
  std::vector<std::string> message_parameters;
  message_parameters.push_back(ExtensionsClient::Get()->GetProductName());
  return Warning(
      kNetworkDelay,
      extension_id,
      IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
      message_parameters);
}

// static
Warning Warning::CreateRepeatedCacheFlushesWarning(
    const std::string& extension_id) {
  std::vector<std::string> message_parameters;
  message_parameters.push_back(ExtensionsClient::Get()->GetProductName());
  return Warning(
      kRepeatedCacheFlushes,
      extension_id,
      IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
      message_parameters);
}

// static
Warning Warning::CreateDownloadFilenameConflictWarning(
    const std::string& losing_extension_id,
    const std::string& winning_extension_id,
    const base::FilePath& losing_filename,
    const base::FilePath& winning_filename) {
  std::vector<std::string> message_parameters;
  message_parameters.push_back(base::UTF16ToUTF8(
      losing_filename.LossyDisplayName()));
  message_parameters.push_back(kTranslate + winning_extension_id);
  message_parameters.push_back(base::UTF16ToUTF8(
      winning_filename.LossyDisplayName()));
  return Warning(
      kDownloadFilenameConflict,
      losing_extension_id,
      IDS_EXTENSION_WARNINGS_DOWNLOAD_FILENAME_CONFLICT,
      message_parameters);
}

// static
Warning Warning::CreateReloadTooFrequentWarning(
    const std::string& extension_id) {
  std::vector<std::string> message_parameters;
  return Warning(kReloadTooFrequent,
                          extension_id,
                          IDS_EXTENSION_WARNING_RELOAD_TOO_FREQUENT,
                          message_parameters);
}

// static
Warning Warning::CreateRulesetFailedToLoadWarning(
    const ExtensionId& extension_id) {
  return Warning(kRulesetFailedToLoad, extension_id,
                 IDS_EXTENSION_WARNING_RULESET_FAILED_TO_LOAD,
                 {} /*message_parameters*/);
}

std::string Warning::GetLocalizedMessage(const ExtensionSet* extensions) const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // These parameters may be unsafe (URLs and Extension names) and need
  // to be HTML-escaped before being embedded in the UI. Also extension IDs
  // are translated to full extension names.
  std::vector<base::string16> final_parameters;
  for (size_t i = 0; i < message_parameters_.size(); ++i) {
    std::string message = message_parameters_[i];
    if (base::StartsWith(message, kTranslate, base::CompareCase::SENSITIVE)) {
      std::string extension_id = message.substr(sizeof(kTranslate) - 1);
      const extensions::Extension* extension =
          extensions->GetByID(extension_id);
      message = extension ? extension->name() : extension_id;
    }
    final_parameters.push_back(base::UTF8ToUTF16(net::EscapeForHTML(message)));
  }

  static_assert(kMaxNumberOfParameters == 4u,
                "You Need To Add More Case Statements");
  switch (final_parameters.size()) {
    case 0:
      return l10n_util::GetStringUTF8(message_id_);
    case 1:
      return l10n_util::GetStringFUTF8(message_id_, final_parameters[0]);
    case 2:
      return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
          final_parameters[1]);
    case 3:
      return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
          final_parameters[1], final_parameters[2]);
    case 4:
      return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
          final_parameters[1], final_parameters[2], final_parameters[3]);
    default:
      NOTREACHED();
      return std::string();
  }
}

bool operator<(const Warning& a, const Warning& b) {
  if (a.extension_id() != b.extension_id())
    return a.extension_id() < b.extension_id();
  return a.warning_type() < b.warning_type();
}

}  // namespace extensions
