| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/character_encoding.h" | 5 #include "chrome/browser/character_encoding.h" |
| 6 | 6 |
| 7 #include <stddef.h> | |
| 8 | |
| 9 #include <map> | |
| 10 #include <memory> | |
| 11 #include <set> | |
| 12 | |
| 13 #include "base/logging.h" | |
| 14 #include "base/macros.h" | 7 #include "base/macros.h" |
| 15 #include "base/strings/string_tokenizer.h" | |
| 16 #include "base/strings/string_util.h" | |
| 17 #include "base/strings/utf_string_conversions.h" | |
| 18 #include "chrome/app/chrome_command_ids.h" | |
| 19 #include "chrome/grit/generated_resources.h" | |
| 20 #include "content/public/browser/browser_thread.h" | |
| 21 #include "third_party/icu/source/common/unicode/ucnv.h" | 8 #include "third_party/icu/source/common/unicode/ucnv.h" |
| 22 #include "ui/base/l10n/l10n_util.h" | |
| 23 #include "ui/base/l10n/l10n_util_collator.h" | |
| 24 | |
| 25 using content::BrowserThread; | |
| 26 | 9 |
| 27 namespace { | 10 namespace { |
| 28 | 11 |
| 29 // The maximum length of short list of recently user selected encodings is 3. | 12 // An array of all supported canonical encoding names. |
| 30 const size_t kUserSelectedEncodingsMaxLength = 3; | 13 const char* const kCanonicalEncodingNames[] = { |
| 14 "Big5", |
| 15 "EUC-JP", |
| 16 "EUC-KR", |
| 17 "gb18030", |
| 18 "GBK", |
| 19 "IBM866", |
| 20 "ISO-2022-JP", |
| 21 "ISO-8859-10", |
| 22 "ISO-8859-13", |
| 23 "ISO-8859-14", |
| 24 "ISO-8859-15", |
| 25 "ISO-8859-16", |
| 26 "ISO-8859-2", |
| 27 "ISO-8859-3", |
| 28 "ISO-8859-4", |
| 29 "ISO-8859-5", |
| 30 "ISO-8859-6", |
| 31 "ISO-8859-7", |
| 32 "ISO-8859-8", |
| 33 "ISO-8859-8-I", |
| 34 "KOI8-R", |
| 35 "KOI8-U", |
| 36 "macintosh", |
| 37 "Shift_JIS", |
| 38 "UTF-16LE", |
| 39 "UTF-8", |
| 40 "windows-1250", |
| 41 "windows-1251", |
| 42 "windows-1252", |
| 43 "windows-1253", |
| 44 "windows-1254", |
| 45 "windows-1255", |
| 46 "windows-1256", |
| 47 "windows-1257", |
| 48 "windows-1258", |
| 49 "windows-874" |
| 50 }; |
| 51 } // namespace |
| 31 | 52 |
| 32 typedef struct { | 53 std::string GetCanonicalEncodingNameByAliasName(const std::string& alias_name) { |
| 33 int resource_id; | 54 for (size_t i = 0; i < arraysize(kCanonicalEncodingNames); ++i) { |
| 34 const char* name; | 55 if (alias_name == kCanonicalEncodingNames[i]) |
| 35 int category_string_id; | 56 return alias_name; |
| 36 } CanonicalEncodingData; | |
| 37 | |
| 38 // An array of all supported canonical encoding names. | |
| 39 const CanonicalEncodingData kCanonicalEncodingNames[] = { | |
| 40 { IDC_ENCODING_UTF8, "UTF-8", IDS_ENCODING_UNICODE }, | |
| 41 { IDC_ENCODING_UTF16LE, "UTF-16LE", IDS_ENCODING_UNICODE }, | |
| 42 { IDC_ENCODING_WINDOWS1252, "windows-1252", IDS_ENCODING_WESTERN }, | |
| 43 { IDC_ENCODING_GBK, "GBK", IDS_ENCODING_SIMP_CHINESE }, | |
| 44 { IDC_ENCODING_GB18030, "gb18030", IDS_ENCODING_SIMP_CHINESE }, | |
| 45 { IDC_ENCODING_BIG5, "Big5", IDS_ENCODING_TRAD_CHINESE }, | |
| 46 { IDC_ENCODING_KOREAN, "EUC-KR", IDS_ENCODING_KOREAN }, | |
| 47 { IDC_ENCODING_SHIFTJIS, "Shift_JIS", IDS_ENCODING_JAPANESE }, | |
| 48 { IDC_ENCODING_EUCJP, "EUC-JP", IDS_ENCODING_JAPANESE }, | |
| 49 { IDC_ENCODING_ISO2022JP, "ISO-2022-JP", IDS_ENCODING_JAPANESE }, | |
| 50 { IDC_ENCODING_THAI, "windows-874", IDS_ENCODING_THAI }, | |
| 51 { IDC_ENCODING_ISO885915, "ISO-8859-15", IDS_ENCODING_WESTERN }, | |
| 52 { IDC_ENCODING_MACINTOSH, "macintosh", IDS_ENCODING_WESTERN }, | |
| 53 { IDC_ENCODING_ISO88592, "ISO-8859-2", IDS_ENCODING_CENTRAL_EUROPEAN }, | |
| 54 { IDC_ENCODING_WINDOWS1250, "windows-1250", IDS_ENCODING_CENTRAL_EUROPEAN }, | |
| 55 { IDC_ENCODING_ISO88595, "ISO-8859-5", IDS_ENCODING_CYRILLIC }, | |
| 56 { IDC_ENCODING_WINDOWS1251, "windows-1251", IDS_ENCODING_CYRILLIC }, | |
| 57 { IDC_ENCODING_KOI8R, "KOI8-R", IDS_ENCODING_CYRILLIC }, | |
| 58 { IDC_ENCODING_KOI8U, "KOI8-U", IDS_ENCODING_CYRILLIC }, | |
| 59 { IDC_ENCODING_IBM866, "IBM866", IDS_ENCODING_CYRILLIC }, | |
| 60 { IDC_ENCODING_ISO88597, "ISO-8859-7", IDS_ENCODING_GREEK }, | |
| 61 { IDC_ENCODING_WINDOWS1253, "windows-1253", IDS_ENCODING_GREEK }, | |
| 62 { IDC_ENCODING_WINDOWS1254, "windows-1254", IDS_ENCODING_TURKISH }, | |
| 63 { IDC_ENCODING_WINDOWS1256, "windows-1256", IDS_ENCODING_ARABIC }, | |
| 64 { IDC_ENCODING_ISO88596, "ISO-8859-6", IDS_ENCODING_ARABIC }, | |
| 65 { IDC_ENCODING_WINDOWS1255, "windows-1255", IDS_ENCODING_HEBREW }, | |
| 66 { IDC_ENCODING_ISO88598I, "ISO-8859-8-I", IDS_ENCODING_HEBREW }, | |
| 67 { IDC_ENCODING_ISO88598, "ISO-8859-8", IDS_ENCODING_HEBREW }, | |
| 68 { IDC_ENCODING_WINDOWS1258, "windows-1258", IDS_ENCODING_VIETNAMESE }, | |
| 69 { IDC_ENCODING_ISO88594, "ISO-8859-4", IDS_ENCODING_BALTIC }, | |
| 70 { IDC_ENCODING_ISO885913, "ISO-8859-13", IDS_ENCODING_BALTIC }, | |
| 71 { IDC_ENCODING_WINDOWS1257, "windows-1257", IDS_ENCODING_BALTIC }, | |
| 72 { IDC_ENCODING_ISO88593, "ISO-8859-3", IDS_ENCODING_SOUTH_EUROPEAN }, | |
| 73 { IDC_ENCODING_ISO885910, "ISO-8859-10", IDS_ENCODING_NORDIC }, | |
| 74 { IDC_ENCODING_ISO885914, "ISO-8859-14", IDS_ENCODING_CELTIC }, | |
| 75 { IDC_ENCODING_ISO885916, "ISO-8859-16", IDS_ENCODING_ROMANIAN }, | |
| 76 }; | |
| 77 | |
| 78 const int kCanonicalEncodingNamesLength = arraysize(kCanonicalEncodingNames); | |
| 79 | |
| 80 typedef std::map<int, std::pair<const char*, int> > | |
| 81 IdToCanonicalEncodingNameMapType; | |
| 82 typedef std::map<const std::string, int> CanonicalEncodingNameToIdMapType; | |
| 83 | |
| 84 typedef struct { | |
| 85 const char* canonical_form; | |
| 86 const char* display_form; | |
| 87 } CanonicalEncodingDisplayNamePair; | |
| 88 | |
| 89 const CanonicalEncodingDisplayNamePair kCanonicalDisplayNameOverrides[] = { | |
| 90 // Only lists the canonical names where we want a different form for display. | |
| 91 { "macintosh", "Macintosh" }, | |
| 92 { "windows-874", "Windows-874" }, | |
| 93 { "windows-1250", "Windows-1250" }, | |
| 94 { "windows-1251", "Windows-1251" }, | |
| 95 { "windows-1252", "Windows-1252" }, | |
| 96 { "windows-1253", "Windows-1253" }, | |
| 97 { "windows-1254", "Windows-1254" }, | |
| 98 { "windows-1255", "Windows-1255" }, | |
| 99 { "windows-1256", "Windows-1256" }, | |
| 100 { "windows-1257", "Windows-1257" }, | |
| 101 { "windows-1258", "Windows-1258" }, | |
| 102 }; | |
| 103 | |
| 104 const int kCanonicalDisplayNameOverridesLength = | |
| 105 arraysize(kCanonicalDisplayNameOverrides); | |
| 106 | |
| 107 typedef std::map<std::string, const char*> CanonicalNameDisplayNameMapType; | |
| 108 | |
| 109 class CanonicalEncodingMap { | |
| 110 public: | |
| 111 CanonicalEncodingMap() {} | |
| 112 const IdToCanonicalEncodingNameMapType* GetIdToCanonicalEncodingNameMapData(); | |
| 113 const CanonicalEncodingNameToIdMapType* GetCanonicalEncodingNameToIdMapData(); | |
| 114 const CanonicalNameDisplayNameMapType* GetCanonicalNameDisplayNameMapData(); | |
| 115 std::vector<int>* locale_dependent_encoding_ids() { | |
| 116 return &locale_dependent_encoding_ids_; | |
| 117 } | 57 } |
| 118 | |
| 119 std::vector<CharacterEncoding::EncodingInfo>* current_display_encodings() { | |
| 120 return ¤t_display_encodings_; | |
| 121 } | |
| 122 | |
| 123 private: | |
| 124 std::unique_ptr<IdToCanonicalEncodingNameMapType> id_to_encoding_name_map_; | |
| 125 std::unique_ptr<CanonicalEncodingNameToIdMapType> encoding_name_to_id_map_; | |
| 126 std::unique_ptr<CanonicalNameDisplayNameMapType> | |
| 127 encoding_name_to_display_name_map_; | |
| 128 std::vector<int> locale_dependent_encoding_ids_; | |
| 129 std::vector<CharacterEncoding::EncodingInfo> current_display_encodings_; | |
| 130 | |
| 131 DISALLOW_COPY_AND_ASSIGN(CanonicalEncodingMap); | |
| 132 }; | |
| 133 | |
| 134 const IdToCanonicalEncodingNameMapType* | |
| 135 CanonicalEncodingMap::GetIdToCanonicalEncodingNameMapData() { | |
| 136 // Testing and building map is not thread safe, this function is supposed to | |
| 137 // only run in UI thread. Myabe I should add a lock in here for making it as | |
| 138 // thread safe. | |
| 139 if (!id_to_encoding_name_map_.get()) { | |
| 140 id_to_encoding_name_map_.reset(new IdToCanonicalEncodingNameMapType); | |
| 141 for (int i = 0; i < kCanonicalEncodingNamesLength; ++i) { | |
| 142 int resource_id = kCanonicalEncodingNames[i].resource_id; | |
| 143 (*id_to_encoding_name_map_)[resource_id] = | |
| 144 std::make_pair(kCanonicalEncodingNames[i].name, | |
| 145 kCanonicalEncodingNames[i].category_string_id); | |
| 146 } | |
| 147 } | |
| 148 return id_to_encoding_name_map_.get(); | |
| 149 } | |
| 150 | |
| 151 const CanonicalEncodingNameToIdMapType* | |
| 152 CanonicalEncodingMap::GetCanonicalEncodingNameToIdMapData() { | |
| 153 if (!encoding_name_to_id_map_.get()) { | |
| 154 encoding_name_to_id_map_.reset(new CanonicalEncodingNameToIdMapType); | |
| 155 for (int i = 0; i < kCanonicalEncodingNamesLength; ++i) { | |
| 156 (*encoding_name_to_id_map_)[kCanonicalEncodingNames[i].name] = | |
| 157 kCanonicalEncodingNames[i].resource_id; | |
| 158 } | |
| 159 } | |
| 160 return encoding_name_to_id_map_.get(); | |
| 161 } | |
| 162 | |
| 163 const CanonicalNameDisplayNameMapType* | |
| 164 CanonicalEncodingMap::GetCanonicalNameDisplayNameMapData() { | |
| 165 if (!encoding_name_to_display_name_map_.get()) { | |
| 166 encoding_name_to_display_name_map_.reset( | |
| 167 new CanonicalNameDisplayNameMapType); | |
| 168 // First store the names in the kCanonicalEncodingNames list. | |
| 169 for (int i = 0; i < kCanonicalEncodingNamesLength; ++i) { | |
| 170 (*encoding_name_to_display_name_map_)[kCanonicalEncodingNames[i].name] = | |
| 171 kCanonicalEncodingNames[i].name; | |
| 172 } | |
| 173 // Then save in the overrides. | |
| 174 for (int i = 0; i < kCanonicalDisplayNameOverridesLength; ++i) { | |
| 175 (*encoding_name_to_display_name_map_) | |
| 176 [kCanonicalDisplayNameOverrides[i].canonical_form] = | |
| 177 kCanonicalDisplayNameOverrides[i].display_form; | |
| 178 } | |
| 179 DCHECK(static_cast<int>(encoding_name_to_display_name_map_->size()) == | |
| 180 kCanonicalEncodingNamesLength) | |
| 181 << "Got an override that wasn't in the encoding list"; | |
| 182 } | |
| 183 return encoding_name_to_display_name_map_.get(); | |
| 184 } | |
| 185 | |
| 186 // A static map object which contains all resourceid-nonsequenced canonical | |
| 187 // encoding names. | |
| 188 CanonicalEncodingMap* CanonicalEncodingMapSingleton() { | |
| 189 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 190 static CanonicalEncodingMap* singleton = new CanonicalEncodingMap; | |
| 191 return singleton; | |
| 192 } | |
| 193 | |
| 194 const int kDefaultEncodingMenus[] = { | |
| 195 IDC_ENCODING_UTF16LE, | |
| 196 IDC_ENCODING_WINDOWS1252, | |
| 197 IDC_ENCODING_GBK, | |
| 198 IDC_ENCODING_GB18030, | |
| 199 IDC_ENCODING_BIG5, | |
| 200 IDC_ENCODING_KOREAN, | |
| 201 IDC_ENCODING_SHIFTJIS, | |
| 202 IDC_ENCODING_EUCJP, | |
| 203 IDC_ENCODING_ISO2022JP, | |
| 204 IDC_ENCODING_THAI, | |
| 205 IDC_ENCODING_ISO885915, | |
| 206 IDC_ENCODING_MACINTOSH, | |
| 207 IDC_ENCODING_ISO88592, | |
| 208 IDC_ENCODING_WINDOWS1250, | |
| 209 IDC_ENCODING_ISO88595, | |
| 210 IDC_ENCODING_WINDOWS1251, | |
| 211 IDC_ENCODING_KOI8R, | |
| 212 IDC_ENCODING_KOI8U, | |
| 213 IDC_ENCODING_IBM866, | |
| 214 IDC_ENCODING_ISO88597, | |
| 215 IDC_ENCODING_WINDOWS1253, | |
| 216 IDC_ENCODING_WINDOWS1254, | |
| 217 IDC_ENCODING_WINDOWS1256, | |
| 218 IDC_ENCODING_ISO88596, | |
| 219 IDC_ENCODING_WINDOWS1255, | |
| 220 IDC_ENCODING_ISO88598I, | |
| 221 IDC_ENCODING_ISO88598, | |
| 222 IDC_ENCODING_WINDOWS1258, | |
| 223 IDC_ENCODING_ISO88594, | |
| 224 IDC_ENCODING_ISO885913, | |
| 225 IDC_ENCODING_WINDOWS1257, | |
| 226 IDC_ENCODING_ISO88593, | |
| 227 IDC_ENCODING_ISO885910, | |
| 228 IDC_ENCODING_ISO885914, | |
| 229 IDC_ENCODING_ISO885916, | |
| 230 }; | |
| 231 | |
| 232 const int kDefaultEncodingMenusLength = arraysize(kDefaultEncodingMenus); | |
| 233 | |
| 234 // Parse the input |encoding_list| which is a encoding list separated with | |
| 235 // comma, get available encoding ids and save them to |available_list|. | |
| 236 // The parameter |maximum_size| indicates maximum size of encoding items we | |
| 237 // want to get from the |encoding_list|. | |
| 238 void ParseEncodingListSeparatedWithComma( | |
| 239 const std::string& encoding_list, std::vector<int>* const available_list, | |
| 240 size_t maximum_size) { | |
| 241 base::StringTokenizer tokenizer(encoding_list, ","); | |
| 242 while (tokenizer.GetNext()) { | |
| 243 int id = CharacterEncoding::GetCommandIdByCanonicalEncodingName( | |
| 244 tokenizer.token()); | |
| 245 // Ignore invalid encoding. | |
| 246 if (!id) | |
| 247 continue; | |
| 248 available_list->push_back(id); | |
| 249 if (available_list->size() == maximum_size) | |
| 250 return; | |
| 251 } | |
| 252 } | |
| 253 | |
| 254 base::string16 GetEncodingDisplayName(const std::string& encoding_name, | |
| 255 int category_string_id) { | |
| 256 base::string16 category_name = l10n_util::GetStringUTF16(category_string_id); | |
| 257 if (category_string_id != IDS_ENCODING_KOREAN && | |
| 258 category_string_id != IDS_ENCODING_THAI && | |
| 259 category_string_id != IDS_ENCODING_TURKISH && | |
| 260 category_string_id != IDS_ENCODING_VIETNAMESE && | |
| 261 category_string_id != IDS_ENCODING_ROMANIAN) { | |
| 262 const CanonicalNameDisplayNameMapType* map = | |
| 263 CanonicalEncodingMapSingleton()->GetCanonicalNameDisplayNameMapData(); | |
| 264 DCHECK(map); | |
| 265 | |
| 266 CanonicalNameDisplayNameMapType::const_iterator found_name = | |
| 267 map->find(encoding_name); | |
| 268 DCHECK(found_name != map->end()); | |
| 269 return l10n_util::GetStringFUTF16(IDS_ENCODING_DISPLAY_TEMPLATE, | |
| 270 category_name, | |
| 271 base::ASCIIToUTF16(found_name->second)); | |
| 272 } | |
| 273 return category_name; | |
| 274 } | |
| 275 | |
| 276 int GetEncodingCategoryStringIdByCommandId(int id) { | |
| 277 const IdToCanonicalEncodingNameMapType* map = | |
| 278 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData(); | |
| 279 DCHECK(map); | |
| 280 | |
| 281 IdToCanonicalEncodingNameMapType::const_iterator found_name = map->find(id); | |
| 282 if (found_name != map->end()) | |
| 283 return found_name->second.second; | |
| 284 return 0; | |
| 285 } | |
| 286 | |
| 287 std::string GetEncodingCategoryStringByCommandId(int id) { | |
| 288 int category_id = GetEncodingCategoryStringIdByCommandId(id); | |
| 289 if (category_id) | |
| 290 return l10n_util::GetStringUTF8(category_id); | |
| 291 return std::string(); | |
| 292 } | |
| 293 | |
| 294 } // namespace | |
| 295 | |
| 296 CharacterEncoding::EncodingInfo::EncodingInfo(int id) | |
| 297 : encoding_id(id) { | |
| 298 encoding_category_name = | |
| 299 base::UTF8ToUTF16(GetEncodingCategoryStringByCommandId(id)); | |
| 300 encoding_display_name = GetCanonicalEncodingDisplayNameByCommandId(id); | |
| 301 } | |
| 302 | |
| 303 // Static. | |
| 304 int CharacterEncoding::GetCommandIdByCanonicalEncodingName( | |
| 305 const std::string& encoding_name) { | |
| 306 const CanonicalEncodingNameToIdMapType* map = | |
| 307 CanonicalEncodingMapSingleton()->GetCanonicalEncodingNameToIdMapData(); | |
| 308 DCHECK(map); | |
| 309 | |
| 310 CanonicalEncodingNameToIdMapType::const_iterator found_id = | |
| 311 map->find(encoding_name); | |
| 312 if (found_id != map->end()) | |
| 313 return found_id->second; | |
| 314 return 0; | |
| 315 } | |
| 316 | |
| 317 // Static. | |
| 318 std::string CharacterEncoding::GetCanonicalEncodingNameByCommandId(int id) { | |
| 319 const IdToCanonicalEncodingNameMapType* map = | |
| 320 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData(); | |
| 321 DCHECK(map); | |
| 322 | |
| 323 IdToCanonicalEncodingNameMapType::const_iterator found_name = map->find(id); | |
| 324 if (found_name != map->end()) | |
| 325 return found_name->second.first; | |
| 326 return std::string(); | |
| 327 } | |
| 328 | |
| 329 // Static. | |
| 330 base::string16 CharacterEncoding::GetCanonicalEncodingDisplayNameByCommandId( | |
| 331 int id) { | |
| 332 const IdToCanonicalEncodingNameMapType* map = | |
| 333 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData(); | |
| 334 DCHECK(map); | |
| 335 | |
| 336 IdToCanonicalEncodingNameMapType::const_iterator found_name = map->find(id); | |
| 337 if (found_name != map->end()) | |
| 338 return GetEncodingDisplayName(found_name->second.first, | |
| 339 found_name->second.second); | |
| 340 return base::string16(); | |
| 341 } | |
| 342 | |
| 343 // Static. | |
| 344 // Return count number of all supported canonical encoding. | |
| 345 int CharacterEncoding::GetSupportCanonicalEncodingCount() { | |
| 346 return kCanonicalEncodingNamesLength; | |
| 347 } | |
| 348 | |
| 349 // Static. | |
| 350 std::string CharacterEncoding::GetCanonicalEncodingNameByIndex(int index) { | |
| 351 if (index < kCanonicalEncodingNamesLength) | |
| 352 return kCanonicalEncodingNames[index].name; | |
| 353 return std::string(); | |
| 354 } | |
| 355 | |
| 356 // Static. | |
| 357 base::string16 CharacterEncoding::GetCanonicalEncodingDisplayNameByIndex( | |
| 358 int index) { | |
| 359 if (index < kCanonicalEncodingNamesLength) | |
| 360 return GetEncodingDisplayName(kCanonicalEncodingNames[index].name, | |
| 361 kCanonicalEncodingNames[index].category_string_id); | |
| 362 return base::string16(); | |
| 363 } | |
| 364 | |
| 365 // Static. | |
| 366 int CharacterEncoding::GetEncodingCommandIdByIndex(int index) { | |
| 367 if (index < kCanonicalEncodingNamesLength) | |
| 368 return kCanonicalEncodingNames[index].resource_id; | |
| 369 return 0; | |
| 370 } | |
| 371 | |
| 372 // Static. | |
| 373 std::string CharacterEncoding::GetCanonicalEncodingNameByAliasName( | |
| 374 const std::string& alias_name) { | |
| 375 // If the input alias_name is already canonical encoding name, just return it. | |
| 376 const CanonicalEncodingNameToIdMapType* map = | |
| 377 CanonicalEncodingMapSingleton()->GetCanonicalEncodingNameToIdMapData(); | |
| 378 DCHECK(map); | |
| 379 | |
| 380 CanonicalEncodingNameToIdMapType::const_iterator found_id = | |
| 381 map->find(alias_name); | |
| 382 if (found_id != map->end()) | |
| 383 return alias_name; | |
| 384 | |
| 385 const char* standards[3] = { "HTML", "MIME", "IANA" }; | 58 const char* standards[3] = { "HTML", "MIME", "IANA" }; |
| 386 for (size_t i = 0; i < arraysize(standards); ++i) { | 59 for (size_t i = 0; i < arraysize(standards); ++i) { |
| 387 UErrorCode error_code = U_ZERO_ERROR; | 60 UErrorCode error_code = U_ZERO_ERROR; |
| 388 const char* canonical_name = ucnv_getCanonicalName( | 61 const char* canonical_name = ucnv_getCanonicalName( |
| 389 alias_name.c_str(), standards[i], &error_code); | 62 alias_name.c_str(), standards[i], &error_code); |
| 390 if (U_SUCCESS(error_code) && canonical_name) | 63 if (U_SUCCESS(error_code) && canonical_name) |
| 391 return canonical_name; | 64 return canonical_name; |
| 392 } | 65 } |
| 393 return std::string(); | 66 return std::string(); |
| 394 } | 67 } |
| 395 | |
| 396 // Static | |
| 397 // According to the behavior of user recently selected encoding short list in | |
| 398 // Firefox, we always put UTF-8 as top position, after then put user | |
| 399 // recent selected encodings, then put local dependent encoding items. | |
| 400 // At last, we put all remaining encoding items. | |
| 401 const std::vector<CharacterEncoding::EncodingInfo>* | |
| 402 CharacterEncoding::GetCurrentDisplayEncodings( | |
| 403 const std::string& locale, | |
| 404 const std::string& locale_encodings, | |
| 405 const std::string& recently_select_encodings) { | |
| 406 std::vector<int>* const locale_dependent_encoding_list = | |
| 407 CanonicalEncodingMapSingleton()->locale_dependent_encoding_ids(); | |
| 408 std::vector<CharacterEncoding::EncodingInfo>* const encoding_list = | |
| 409 CanonicalEncodingMapSingleton()->current_display_encodings(); | |
| 410 | |
| 411 // Initialize locale dependent static encoding list. | |
| 412 if (locale_dependent_encoding_list->empty() && !locale_encodings.empty()) | |
| 413 ParseEncodingListSeparatedWithComma(locale_encodings, | |
| 414 locale_dependent_encoding_list, | |
| 415 kUserSelectedEncodingsMaxLength); | |
| 416 | |
| 417 CR_DEFINE_STATIC_LOCAL(std::string, cached_user_selected_encodings, ()); | |
| 418 // Build current display encoding list. | |
| 419 if (encoding_list->empty() || | |
| 420 cached_user_selected_encodings != recently_select_encodings) { | |
| 421 // Update user recently selected encodings. | |
| 422 cached_user_selected_encodings = recently_select_encodings; | |
| 423 // Clear old encoding list since user recently selected encodings changed. | |
| 424 encoding_list->clear(); | |
| 425 // Always add UTF-8 to first encoding position. | |
| 426 encoding_list->push_back(EncodingInfo(IDC_ENCODING_UTF8)); | |
| 427 std::set<int> inserted_encoding; | |
| 428 inserted_encoding.insert(IDC_ENCODING_UTF8); | |
| 429 | |
| 430 // Parse user recently selected encodings and get list | |
| 431 std::vector<int> recently_select_encoding_list; | |
| 432 ParseEncodingListSeparatedWithComma(recently_select_encodings, | |
| 433 &recently_select_encoding_list, | |
| 434 kUserSelectedEncodingsMaxLength); | |
| 435 | |
| 436 // Put 'cached encodings' (dynamic encoding list) after 'local dependent | |
| 437 // encoding list'. | |
| 438 recently_select_encoding_list.insert(recently_select_encoding_list.begin(), | |
| 439 locale_dependent_encoding_list->begin(), | |
| 440 locale_dependent_encoding_list->end()); | |
| 441 for (std::vector<int>::iterator it = recently_select_encoding_list.begin(); | |
| 442 it != recently_select_encoding_list.end(); ++it) { | |
| 443 // Test whether we have met this encoding id. | |
| 444 bool ok = inserted_encoding.insert(*it).second; | |
| 445 // Duplicated encoding, ignore it. Ideally, this situation should not | |
| 446 // happened, but just in case some one manually edit preference file. | |
| 447 if (!ok) | |
| 448 continue; | |
| 449 encoding_list->push_back(EncodingInfo(*it)); | |
| 450 } | |
| 451 // Append a separator; | |
| 452 encoding_list->push_back(EncodingInfo(0)); | |
| 453 | |
| 454 // We need to keep "Unicode (UTF-16LE)" always at the top (among the rest | |
| 455 // of encodings) instead of being sorted along with other encodings. So if | |
| 456 // "Unicode (UTF-16LE)" is already in previous encodings, sort the rest | |
| 457 // of encodings. Otherwise Put "Unicode (UTF-16LE)" on the first of the | |
| 458 // rest of encodings, skip "Unicode (UTF-16LE)" and sort all left encodings. | |
| 459 int start_sorted_index = encoding_list->size(); | |
| 460 if (inserted_encoding.find(IDC_ENCODING_UTF16LE) == | |
| 461 inserted_encoding.end()) { | |
| 462 encoding_list->push_back(EncodingInfo(IDC_ENCODING_UTF16LE)); | |
| 463 inserted_encoding.insert(IDC_ENCODING_UTF16LE); | |
| 464 start_sorted_index++; | |
| 465 } | |
| 466 | |
| 467 // Add the rest of encodings that are neither in the static encoding list | |
| 468 // nor in the list of recently selected encodings. | |
| 469 // Build the encoding list sorted in the current locale sorting order. | |
| 470 for (int i = 0; i < kDefaultEncodingMenusLength; ++i) { | |
| 471 int id = kDefaultEncodingMenus[i]; | |
| 472 // We have inserted this encoding, skip it. | |
| 473 if (inserted_encoding.find(id) != inserted_encoding.end()) | |
| 474 continue; | |
| 475 encoding_list->push_back(EncodingInfo(id)); | |
| 476 } | |
| 477 // Sort the encoding list. | |
| 478 l10n_util::SortVectorWithStringKey(locale, | |
| 479 encoding_list, | |
| 480 start_sorted_index, | |
| 481 encoding_list->size(), | |
| 482 true); | |
| 483 } | |
| 484 DCHECK(!encoding_list->empty()); | |
| 485 return encoding_list; | |
| 486 } | |
| 487 | |
| 488 // Static | |
| 489 bool CharacterEncoding::UpdateRecentlySelectedEncoding( | |
| 490 const std::string& original_selected_encodings, | |
| 491 int new_selected_encoding_id, | |
| 492 std::string* selected_encodings) { | |
| 493 // Get encoding name. | |
| 494 std::string encoding_name = | |
| 495 GetCanonicalEncodingNameByCommandId(new_selected_encoding_id); | |
| 496 DCHECK(!encoding_name.empty()); | |
| 497 // Check whether the new encoding is in local dependent encodings or original | |
| 498 // recently selected encodings. If yes, do not add it. | |
| 499 std::vector<int>* locale_dependent_encoding_list = | |
| 500 CanonicalEncodingMapSingleton()->locale_dependent_encoding_ids(); | |
| 501 DCHECK(locale_dependent_encoding_list); | |
| 502 std::vector<int> selected_encoding_list; | |
| 503 ParseEncodingListSeparatedWithComma(original_selected_encodings, | |
| 504 &selected_encoding_list, | |
| 505 kUserSelectedEncodingsMaxLength); | |
| 506 // Put 'cached encodings' (dynamic encoding list) after 'local dependent | |
| 507 // encoding list' for check. | |
| 508 std::vector<int> top_encoding_list(*locale_dependent_encoding_list); | |
| 509 // UTF8 is always in our optimized encoding list. | |
| 510 top_encoding_list.insert(top_encoding_list.begin(), IDC_ENCODING_UTF8); | |
| 511 top_encoding_list.insert(top_encoding_list.end(), | |
| 512 selected_encoding_list.begin(), | |
| 513 selected_encoding_list.end()); | |
| 514 for (std::vector<int>::const_iterator it = top_encoding_list.begin(); | |
| 515 it != top_encoding_list.end(); ++it) | |
| 516 if (*it == new_selected_encoding_id) | |
| 517 return false; | |
| 518 // Need to add the encoding id to recently selected encoding list. | |
| 519 // Remove the last encoding in original list. | |
| 520 if (selected_encoding_list.size() == kUserSelectedEncodingsMaxLength) | |
| 521 selected_encoding_list.pop_back(); | |
| 522 // Insert new encoding to head of selected encoding list. | |
| 523 *selected_encodings = encoding_name; | |
| 524 // Generate the string for rest selected encoding list. | |
| 525 for (std::vector<int>::const_iterator it = selected_encoding_list.begin(); | |
| 526 it != selected_encoding_list.end(); ++it) { | |
| 527 selected_encodings->append(1, L','); | |
| 528 selected_encodings->append(GetCanonicalEncodingNameByCommandId(*it)); | |
| 529 } | |
| 530 return true; | |
| 531 } | |
| OLD | NEW |