Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/extensions/extension_warning_set.h"
      6 
      7 #include "base/files/file_path.h"
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "chrome/browser/chrome_notification_types.h"
     10 #include "chrome/common/extensions/extension_set.h"
     11 #include "content/public/browser/browser_thread.h"
     12 #include "extensions/common/extension.h"
     13 #include "grit/chromium_strings.h"
     14 #include "grit/generated_resources.h"
     15 #include "net/base/escape.h"
     16 #include "ui/base/l10n/l10n_util.h"
     17 
     18 using content::BrowserThread;
     19 
     20 namespace {
     21 // Prefix for message parameters indicating that the parameter needs to
     22 // be translated from an extension id to the extension name.
     23 const char kTranslate[] = "TO_TRANSLATE:";
     24 const size_t kMaxNumberOfParameters = 4;
     25 }
     26 
     27 namespace extensions {
     28 
     29 //
     30 // ExtensionWarning
     31 //
     32 
     33 ExtensionWarning::ExtensionWarning(
     34     WarningType type,
     35     const std::string& extension_id,
     36     int message_id,
     37     const std::vector<std::string>& message_parameters)
     38     : type_(type),
     39       extension_id_(extension_id),
     40       message_id_(message_id),
     41       message_parameters_(message_parameters) {
     42   // These are invalid here because they do not have corresponding warning
     43   // messages in the UI.
     44   CHECK_NE(type, kInvalid);
     45   CHECK_NE(type, kMaxWarningType);
     46   CHECK_LE(message_parameters.size(), kMaxNumberOfParameters);
     47 }
     48 
     49 ExtensionWarning::ExtensionWarning(const ExtensionWarning& other)
     50   : type_(other.type_),
     51     extension_id_(other.extension_id_),
     52     message_id_(other.message_id_),
     53     message_parameters_(other.message_parameters_) {}
     54 
     55 ExtensionWarning::~ExtensionWarning() {
     56 }
     57 
     58 ExtensionWarning& ExtensionWarning::operator=(const ExtensionWarning& other) {
     59   type_ = other.type_;
     60   extension_id_ = other.extension_id_;
     61   message_id_ = other.message_id_;
     62   message_parameters_ = other.message_parameters_;
     63   return *this;
     64 }
     65 
     66 // static
     67 ExtensionWarning ExtensionWarning::CreateNetworkDelayWarning(
     68     const std::string& extension_id) {
     69   std::vector<std::string> message_parameters;
     70   message_parameters.push_back(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
     71   return ExtensionWarning(
     72       kNetworkDelay,
     73       extension_id,
     74       IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
     75       message_parameters);
     76 }
     77 
     78 // static
     79 ExtensionWarning ExtensionWarning::CreateNetworkConflictWarning(
     80     const std::string& extension_id) {
     81   std::vector<std::string> message_parameters;
     82   return ExtensionWarning(
     83       kNetworkConflict,
     84       extension_id,
     85       IDS_EXTENSION_WARNINGS_NETWORK_CONFLICT,
     86       message_parameters);
     87 }
     88 
     89 // static
     90 ExtensionWarning ExtensionWarning::CreateRedirectConflictWarning(
     91     const std::string& extension_id,
     92     const std::string& winning_extension_id,
     93     const GURL& attempted_redirect_url,
     94     const GURL& winning_redirect_url) {
     95   std::vector<std::string> message_parameters;
     96   message_parameters.push_back(attempted_redirect_url.spec());
     97   message_parameters.push_back(kTranslate + winning_extension_id);
     98   message_parameters.push_back(winning_redirect_url.spec());
     99   return ExtensionWarning(
    100       kRedirectConflict,
    101       extension_id,
    102       IDS_EXTENSION_WARNINGS_REDIRECT_CONFLICT,
    103       message_parameters);
    104 }
    105 
    106 // static
    107 ExtensionWarning ExtensionWarning::CreateRequestHeaderConflictWarning(
    108     const std::string& extension_id,
    109     const std::string& winning_extension_id,
    110     const std::string& conflicting_header) {
    111   std::vector<std::string> message_parameters;
    112   message_parameters.push_back(conflicting_header);
    113   message_parameters.push_back(kTranslate + winning_extension_id);
    114   return ExtensionWarning(
    115       kNetworkConflict,
    116       extension_id,
    117       IDS_EXTENSION_WARNINGS_REQUEST_HEADER_CONFLICT,
    118       message_parameters);
    119 }
    120 
    121 // static
    122 ExtensionWarning ExtensionWarning::CreateResponseHeaderConflictWarning(
    123     const std::string& extension_id,
    124     const std::string& winning_extension_id,
    125     const std::string& conflicting_header) {
    126   std::vector<std::string> message_parameters;
    127   message_parameters.push_back(conflicting_header);
    128   message_parameters.push_back(kTranslate + winning_extension_id);
    129   return ExtensionWarning(
    130       kNetworkConflict,
    131       extension_id,
    132       IDS_EXTENSION_WARNINGS_RESPONSE_HEADER_CONFLICT,
    133       message_parameters);
    134 }
    135 
    136 // static
    137 ExtensionWarning ExtensionWarning::CreateCredentialsConflictWarning(
    138     const std::string& extension_id,
    139     const std::string& winning_extension_id) {
    140   std::vector<std::string> message_parameters;
    141   message_parameters.push_back(kTranslate + winning_extension_id);
    142   return ExtensionWarning(
    143       kNetworkConflict,
    144       extension_id,
    145       IDS_EXTENSION_WARNINGS_CREDENTIALS_CONFLICT,
    146       message_parameters);
    147 }
    148 
    149 // static
    150 ExtensionWarning ExtensionWarning::CreateRepeatedCacheFlushesWarning(
    151     const std::string& extension_id) {
    152   std::vector<std::string> message_parameters;
    153   message_parameters.push_back(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
    154   return ExtensionWarning(
    155       kRepeatedCacheFlushes,
    156       extension_id,
    157       IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
    158       message_parameters);
    159 }
    160 
    161 // static
    162 ExtensionWarning ExtensionWarning::CreateDownloadFilenameConflictWarning(
    163     const std::string& losing_extension_id,
    164     const std::string& winning_extension_id,
    165     const base::FilePath& losing_filename,
    166     const base::FilePath& winning_filename) {
    167   std::vector<std::string> message_parameters;
    168   message_parameters.push_back(UTF16ToUTF8(losing_filename.LossyDisplayName()));
    169   message_parameters.push_back(kTranslate + winning_extension_id);
    170   message_parameters.push_back(UTF16ToUTF8(
    171       winning_filename.LossyDisplayName()));
    172   return ExtensionWarning(
    173       kDownloadFilenameConflict,
    174       losing_extension_id,
    175       IDS_EXTENSION_WARNINGS_DOWNLOAD_FILENAME_CONFLICT,
    176       message_parameters);
    177 }
    178 
    179 std::string ExtensionWarning::GetLocalizedMessage(
    180     const ExtensionSet* extensions) const {
    181   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    182 
    183   // These parameters may be unsafe (URLs and Extension names) and need
    184   // to be HTML-escaped before being embedded in the UI. Also extension IDs
    185   // are translated to full extension names.
    186   std::vector<base::string16> final_parameters;
    187   for (size_t i = 0; i < message_parameters_.size(); ++i) {
    188     std::string message = message_parameters_[i];
    189     if (StartsWithASCII(message, kTranslate, true)) {
    190       std::string extension_id = message.substr(sizeof(kTranslate) - 1);
    191       const extensions::Extension* extension =
    192           extensions->GetByID(extension_id);
    193       message = extension ? extension->name() : extension_id;
    194     }
    195     final_parameters.push_back(UTF8ToUTF16(net::EscapeForHTML(message)));
    196   }
    197 
    198   COMPILE_ASSERT(kMaxNumberOfParameters == 4u, YouNeedToAddMoreCaseStatements);
    199   switch (final_parameters.size()) {
    200     case 0:
    201       return l10n_util::GetStringUTF8(message_id_);
    202     case 1:
    203       return l10n_util::GetStringFUTF8(message_id_, final_parameters[0]);
    204     case 2:
    205       return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
    206           final_parameters[1]);
    207     case 3:
    208       return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
    209           final_parameters[1], final_parameters[2]);
    210     case 4:
    211       return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
    212           final_parameters[1], final_parameters[2], final_parameters[3]);
    213     default:
    214       NOTREACHED();
    215       return std::string();
    216   }
    217 }
    218 
    219 bool operator<(const ExtensionWarning& a, const ExtensionWarning& b) {
    220   if (a.extension_id() != b.extension_id())
    221     return a.extension_id() < b.extension_id();
    222   return a.warning_type() < b.warning_type();
    223 }
    224 
    225 }  // namespace extensions
    226