Home | History | Annotate | Download | only in browser
      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 "extensions/browser/warning_set.h"
      6 
      7 #include "base/files/file_path.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "content/public/browser/browser_thread.h"
     11 #include "extensions/common/extension.h"
     12 #include "extensions/common/extension_set.h"
     13 #include "extensions/common/extensions_client.h"
     14 #include "extensions/strings/grit/extensions_strings.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 // Warning
     31 //
     32 
     33 Warning::Warning(
     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 Warning::Warning(const Warning& 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 Warning::~Warning() {
     56 }
     57 
     58 Warning& Warning::operator=(const Warning& 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 Warning Warning::CreateNetworkDelayWarning(
     68     const std::string& extension_id) {
     69   std::vector<std::string> message_parameters;
     70   message_parameters.push_back(ExtensionsClient::Get()->GetProductName());
     71   return Warning(
     72       kNetworkDelay,
     73       extension_id,
     74       IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
     75       message_parameters);
     76 }
     77 
     78 // static
     79 Warning Warning::CreateNetworkConflictWarning(const std::string& extension_id) {
     80   std::vector<std::string> message_parameters;
     81   return Warning(
     82       kNetworkConflict,
     83       extension_id,
     84       IDS_EXTENSION_WARNINGS_NETWORK_CONFLICT,
     85       message_parameters);
     86 }
     87 
     88 // static
     89 Warning Warning::CreateRedirectConflictWarning(
     90     const std::string& extension_id,
     91     const std::string& winning_extension_id,
     92     const GURL& attempted_redirect_url,
     93     const GURL& winning_redirect_url) {
     94   std::vector<std::string> message_parameters;
     95   message_parameters.push_back(attempted_redirect_url.spec());
     96   message_parameters.push_back(kTranslate + winning_extension_id);
     97   message_parameters.push_back(winning_redirect_url.spec());
     98   return Warning(
     99       kRedirectConflict,
    100       extension_id,
    101       IDS_EXTENSION_WARNINGS_REDIRECT_CONFLICT,
    102       message_parameters);
    103 }
    104 
    105 // static
    106 Warning Warning::CreateRequestHeaderConflictWarning(
    107     const std::string& extension_id,
    108     const std::string& winning_extension_id,
    109     const std::string& conflicting_header) {
    110   std::vector<std::string> message_parameters;
    111   message_parameters.push_back(conflicting_header);
    112   message_parameters.push_back(kTranslate + winning_extension_id);
    113   return Warning(
    114       kNetworkConflict,
    115       extension_id,
    116       IDS_EXTENSION_WARNINGS_REQUEST_HEADER_CONFLICT,
    117       message_parameters);
    118 }
    119 
    120 // static
    121 Warning Warning::CreateResponseHeaderConflictWarning(
    122     const std::string& extension_id,
    123     const std::string& winning_extension_id,
    124     const std::string& conflicting_header) {
    125   std::vector<std::string> message_parameters;
    126   message_parameters.push_back(conflicting_header);
    127   message_parameters.push_back(kTranslate + winning_extension_id);
    128   return Warning(
    129       kNetworkConflict,
    130       extension_id,
    131       IDS_EXTENSION_WARNINGS_RESPONSE_HEADER_CONFLICT,
    132       message_parameters);
    133 }
    134 
    135 // static
    136 Warning Warning::CreateCredentialsConflictWarning(
    137     const std::string& extension_id,
    138     const std::string& winning_extension_id) {
    139   std::vector<std::string> message_parameters;
    140   message_parameters.push_back(kTranslate + winning_extension_id);
    141   return Warning(
    142       kNetworkConflict,
    143       extension_id,
    144       IDS_EXTENSION_WARNINGS_CREDENTIALS_CONFLICT,
    145       message_parameters);
    146 }
    147 
    148 // static
    149 Warning Warning::CreateRepeatedCacheFlushesWarning(
    150     const std::string& extension_id) {
    151   std::vector<std::string> message_parameters;
    152   message_parameters.push_back(ExtensionsClient::Get()->GetProductName());
    153   return Warning(
    154       kRepeatedCacheFlushes,
    155       extension_id,
    156       IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
    157       message_parameters);
    158 }
    159 
    160 // static
    161 Warning Warning::CreateDownloadFilenameConflictWarning(
    162     const std::string& losing_extension_id,
    163     const std::string& winning_extension_id,
    164     const base::FilePath& losing_filename,
    165     const base::FilePath& winning_filename) {
    166   std::vector<std::string> message_parameters;
    167   message_parameters.push_back(base::UTF16ToUTF8(
    168       losing_filename.LossyDisplayName()));
    169   message_parameters.push_back(kTranslate + winning_extension_id);
    170   message_parameters.push_back(base::UTF16ToUTF8(
    171       winning_filename.LossyDisplayName()));
    172   return Warning(
    173       kDownloadFilenameConflict,
    174       losing_extension_id,
    175       IDS_EXTENSION_WARNINGS_DOWNLOAD_FILENAME_CONFLICT,
    176       message_parameters);
    177 }
    178 
    179 // static
    180 Warning Warning::CreateReloadTooFrequentWarning(
    181     const std::string& extension_id) {
    182   std::vector<std::string> message_parameters;
    183   return Warning(kReloadTooFrequent,
    184                           extension_id,
    185                           IDS_EXTENSION_WARNING_RELOAD_TOO_FREQUENT,
    186                           message_parameters);
    187 }
    188 
    189 std::string Warning::GetLocalizedMessage(const ExtensionSet* extensions) const {
    190   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    191 
    192   // These parameters may be unsafe (URLs and Extension names) and need
    193   // to be HTML-escaped before being embedded in the UI. Also extension IDs
    194   // are translated to full extension names.
    195   std::vector<base::string16> final_parameters;
    196   for (size_t i = 0; i < message_parameters_.size(); ++i) {
    197     std::string message = message_parameters_[i];
    198     if (StartsWithASCII(message, kTranslate, true)) {
    199       std::string extension_id = message.substr(sizeof(kTranslate) - 1);
    200       const extensions::Extension* extension =
    201           extensions->GetByID(extension_id);
    202       message = extension ? extension->name() : extension_id;
    203     }
    204     final_parameters.push_back(base::UTF8ToUTF16(net::EscapeForHTML(message)));
    205   }
    206 
    207   COMPILE_ASSERT(kMaxNumberOfParameters == 4u, YouNeedToAddMoreCaseStatements);
    208   switch (final_parameters.size()) {
    209     case 0:
    210       return l10n_util::GetStringUTF8(message_id_);
    211     case 1:
    212       return l10n_util::GetStringFUTF8(message_id_, final_parameters[0]);
    213     case 2:
    214       return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
    215           final_parameters[1]);
    216     case 3:
    217       return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
    218           final_parameters[1], final_parameters[2]);
    219     case 4:
    220       return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
    221           final_parameters[1], final_parameters[2], final_parameters[3]);
    222     default:
    223       NOTREACHED();
    224       return std::string();
    225   }
    226 }
    227 
    228 bool operator<(const Warning& a, const Warning& b) {
    229   if (a.extension_id() != b.extension_id())
    230     return a.extension_id() < b.extension_id();
    231   return a.warning_type() < b.warning_type();
    232 }
    233 
    234 }  // namespace extensions
    235