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