普通文本  |  237行  |  7.96 KB

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

#include "base/files/file_path.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.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 {

//
// ExtensionWarning
//

ExtensionWarning::ExtensionWarning(
    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);
}

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

ExtensionWarning::~ExtensionWarning() {
}

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

// static
ExtensionWarning ExtensionWarning::CreateNetworkDelayWarning(
    const std::string& extension_id) {
  std::vector<std::string> message_parameters;
  message_parameters.push_back(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
  return ExtensionWarning(
      kNetworkDelay,
      extension_id,
      IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
      message_parameters);
}

// static
ExtensionWarning ExtensionWarning::CreateNetworkConflictWarning(
    const std::string& extension_id) {
  std::vector<std::string> message_parameters;
  return ExtensionWarning(
      kNetworkConflict,
      extension_id,
      IDS_EXTENSION_WARNINGS_NETWORK_CONFLICT,
      message_parameters);
}

// static
ExtensionWarning ExtensionWarning::CreateRedirectConflictWarning(
    const std::string& extension_id,
    const std::string& winning_extension_id,
    const GURL& attempted_redirect_url,
    const GURL& winning_redirect_url) {
  std::vector<std::string> message_parameters;
  message_parameters.push_back(attempted_redirect_url.spec());
  message_parameters.push_back(kTranslate + winning_extension_id);
  message_parameters.push_back(winning_redirect_url.spec());
  return ExtensionWarning(
      kRedirectConflict,
      extension_id,
      IDS_EXTENSION_WARNINGS_REDIRECT_CONFLICT,
      message_parameters);
}

// static
ExtensionWarning ExtensionWarning::CreateRequestHeaderConflictWarning(
    const std::string& extension_id,
    const std::string& winning_extension_id,
    const std::string& conflicting_header) {
  std::vector<std::string> message_parameters;
  message_parameters.push_back(conflicting_header);
  message_parameters.push_back(kTranslate + winning_extension_id);
  return ExtensionWarning(
      kNetworkConflict,
      extension_id,
      IDS_EXTENSION_WARNINGS_REQUEST_HEADER_CONFLICT,
      message_parameters);
}

// static
ExtensionWarning ExtensionWarning::CreateResponseHeaderConflictWarning(
    const std::string& extension_id,
    const std::string& winning_extension_id,
    const std::string& conflicting_header) {
  std::vector<std::string> message_parameters;
  message_parameters.push_back(conflicting_header);
  message_parameters.push_back(kTranslate + winning_extension_id);
  return ExtensionWarning(
      kNetworkConflict,
      extension_id,
      IDS_EXTENSION_WARNINGS_RESPONSE_HEADER_CONFLICT,
      message_parameters);
}

// static
ExtensionWarning ExtensionWarning::CreateCredentialsConflictWarning(
    const std::string& extension_id,
    const std::string& winning_extension_id) {
  std::vector<std::string> message_parameters;
  message_parameters.push_back(kTranslate + winning_extension_id);
  return ExtensionWarning(
      kNetworkConflict,
      extension_id,
      IDS_EXTENSION_WARNINGS_CREDENTIALS_CONFLICT,
      message_parameters);
}

// static
ExtensionWarning ExtensionWarning::CreateRepeatedCacheFlushesWarning(
    const std::string& extension_id) {
  std::vector<std::string> message_parameters;
  message_parameters.push_back(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
  return ExtensionWarning(
      kRepeatedCacheFlushes,
      extension_id,
      IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
      message_parameters);
}

// static
ExtensionWarning ExtensionWarning::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 ExtensionWarning(
      kDownloadFilenameConflict,
      losing_extension_id,
      IDS_EXTENSION_WARNINGS_DOWNLOAD_FILENAME_CONFLICT,
      message_parameters);
}

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

std::string ExtensionWarning::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 (StartsWithASCII(message, kTranslate, true)) {
      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)));
  }

  COMPILE_ASSERT(kMaxNumberOfParameters == 4u, YouNeedToAddMoreCaseStatements);
  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 ExtensionWarning& a, const ExtensionWarning& b) {
  if (a.extension_id() != b.extension_id())
    return a.extension_id() < b.extension_id();
  return a.warning_type() < b.warning_type();
}

}  // namespace extensions