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