15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/character_encoding.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_tokenizer.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/app/chrome_command_ids.h"
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "third_party/icu/source/common/unicode/ucnv.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util_collator.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum length of short list of recently user selected encodings is 3.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kUserSelectedEncodingsMaxLength = 3;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int resource_id;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* name;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int category_string_id;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} CanonicalEncodingData;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An array of all supported canonical encoding names.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const CanonicalEncodingData kCanonicalEncodingNames[] = {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_UTF8, "UTF-8", IDS_ENCODING_UNICODE },
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_UTF16LE, "UTF-16LE", IDS_ENCODING_UNICODE },
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO88591, "ISO-8859-1", IDS_ENCODING_WESTERN },
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_WINDOWS1252, "windows-1252", IDS_ENCODING_WESTERN },
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_GBK, "GBK", IDS_ENCODING_SIMP_CHINESE },
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_GB18030, "gb18030", IDS_ENCODING_SIMP_CHINESE },
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_BIG5, "Big5", IDS_ENCODING_TRAD_CHINESE },
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_BIG5HKSCS, "Big5-HKSCS", IDS_ENCODING_TRAD_CHINESE },
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  { IDC_ENCODING_KOREAN, "EUC-KR", IDS_ENCODING_KOREAN },
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_SHIFTJIS, "Shift_JIS", IDS_ENCODING_JAPANESE },
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_EUCJP, "EUC-JP", IDS_ENCODING_JAPANESE },
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO2022JP, "ISO-2022-JP", IDS_ENCODING_JAPANESE },
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_THAI, "windows-874", IDS_ENCODING_THAI },
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO885915, "ISO-8859-15", IDS_ENCODING_WESTERN },
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_MACINTOSH, "macintosh", IDS_ENCODING_WESTERN },
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO88592, "ISO-8859-2", IDS_ENCODING_CENTRAL_EUROPEAN },
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_WINDOWS1250, "windows-1250", IDS_ENCODING_CENTRAL_EUROPEAN },
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO88595, "ISO-8859-5", IDS_ENCODING_CYRILLIC },
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_WINDOWS1251, "windows-1251", IDS_ENCODING_CYRILLIC },
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_KOI8R, "KOI8-R", IDS_ENCODING_CYRILLIC },
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_KOI8U, "KOI8-U", IDS_ENCODING_CYRILLIC },
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO88597, "ISO-8859-7", IDS_ENCODING_GREEK },
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_WINDOWS1253, "windows-1253", IDS_ENCODING_GREEK },
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_WINDOWS1254, "windows-1254", IDS_ENCODING_TURKISH },
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_WINDOWS1256, "windows-1256", IDS_ENCODING_ARABIC },
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO88596, "ISO-8859-6", IDS_ENCODING_ARABIC },
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_WINDOWS1255, "windows-1255", IDS_ENCODING_HEBREW },
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO88598I, "ISO-8859-8-I", IDS_ENCODING_HEBREW },
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO88598, "ISO-8859-8", IDS_ENCODING_HEBREW },
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_WINDOWS1258, "windows-1258", IDS_ENCODING_VIETNAMESE },
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO88594, "ISO-8859-4", IDS_ENCODING_BALTIC },
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO885913, "ISO-8859-13", IDS_ENCODING_BALTIC },
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_WINDOWS1257, "windows-1257", IDS_ENCODING_BALTIC },
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO88593, "ISO-8859-3", IDS_ENCODING_SOUTH_EUROPEAN },
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO885910, "ISO-8859-10", IDS_ENCODING_NORDIC },
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO885914, "ISO-8859-14", IDS_ENCODING_CELTIC },
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { IDC_ENCODING_ISO885916, "ISO-8859-16", IDS_ENCODING_ROMANIAN },
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kCanonicalEncodingNamesLength = arraysize(kCanonicalEncodingNames);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::map<int, std::pair<const char*, int> >
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdToCanonicalEncodingNameMapType;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::map<const std::string, int> CanonicalEncodingNameToIdMapType;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* canonical_form;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* display_form;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} CanonicalEncodingDisplayNamePair;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const CanonicalEncodingDisplayNamePair kCanonicalDisplayNameOverrides[] = {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only lists the canonical names where we want a different form for display.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "macintosh", "Macintosh" },
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "windows-874", "Windows-874" },
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "windows-1250", "Windows-1250" },
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "windows-1251", "Windows-1251" },
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "windows-1252", "Windows-1252" },
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "windows-1253", "Windows-1253" },
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "windows-1254", "Windows-1254" },
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "windows-1255", "Windows-1255" },
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "windows-1256", "Windows-1256" },
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "windows-1257", "Windows-1257" },
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "windows-1258", "Windows-1258" },
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kCanonicalDisplayNameOverridesLength =
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arraysize(kCanonicalDisplayNameOverrides);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::map<std::string, const char*> CanonicalNameDisplayNameMapType;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CanonicalEncodingMap {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CanonicalEncodingMap() {}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const IdToCanonicalEncodingNameMapType* GetIdToCanonicalEncodingNameMapData();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CanonicalEncodingNameToIdMapType* GetCanonicalEncodingNameToIdMapData();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CanonicalNameDisplayNameMapType* GetCanonicalNameDisplayNameMapData();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int>* locale_dependent_encoding_ids() {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &locale_dependent_encoding_ids_;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CharacterEncoding::EncodingInfo>* current_display_encodings() {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &current_display_encodings_;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<IdToCanonicalEncodingNameMapType> id_to_encoding_name_map_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<CanonicalEncodingNameToIdMapType> encoding_name_to_id_map_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<CanonicalNameDisplayNameMapType>
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      encoding_name_to_display_name_map_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> locale_dependent_encoding_ids_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CharacterEncoding::EncodingInfo> current_display_encodings_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CanonicalEncodingMap);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const IdToCanonicalEncodingNameMapType*
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CanonicalEncodingMap::GetIdToCanonicalEncodingNameMapData() {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Testing and building map is not thread safe, this function is supposed to
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only run in UI thread. Myabe I should add a lock in here for making it as
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread safe.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!id_to_encoding_name_map_.get()) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    id_to_encoding_name_map_.reset(new IdToCanonicalEncodingNameMapType);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kCanonicalEncodingNamesLength; ++i) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int resource_id = kCanonicalEncodingNames[i].resource_id;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*id_to_encoding_name_map_)[resource_id] =
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::make_pair(kCanonicalEncodingNames[i].name,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       kCanonicalEncodingNames[i].category_string_id);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return id_to_encoding_name_map_.get();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const CanonicalEncodingNameToIdMapType*
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CanonicalEncodingMap::GetCanonicalEncodingNameToIdMapData() {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!encoding_name_to_id_map_.get()) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encoding_name_to_id_map_.reset(new CanonicalEncodingNameToIdMapType);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kCanonicalEncodingNamesLength; ++i) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*encoding_name_to_id_map_)[kCanonicalEncodingNames[i].name] =
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kCanonicalEncodingNames[i].resource_id;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return encoding_name_to_id_map_.get();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const CanonicalNameDisplayNameMapType*
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CanonicalEncodingMap::GetCanonicalNameDisplayNameMapData() {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!encoding_name_to_display_name_map_.get()) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encoding_name_to_display_name_map_.reset(
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new CanonicalNameDisplayNameMapType);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First store the names in the kCanonicalEncodingNames list.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kCanonicalEncodingNamesLength; ++i) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*encoding_name_to_display_name_map_)[kCanonicalEncodingNames[i].name] =
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kCanonicalEncodingNames[i].name;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Then save in the overrides.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kCanonicalDisplayNameOverridesLength; ++i) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*encoding_name_to_display_name_map_)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          [kCanonicalDisplayNameOverrides[i].canonical_form] =
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kCanonicalDisplayNameOverrides[i].display_form;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(static_cast<int>(encoding_name_to_display_name_map_->size()) ==
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           kCanonicalEncodingNamesLength)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Got an override that wasn't in the encoding list";
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return encoding_name_to_display_name_map_.get();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A static map object which contains all resourceid-nonsequenced canonical
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// encoding names.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CanonicalEncodingMap* CanonicalEncodingMapSingleton() {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static CanonicalEncodingMap* singleton = new CanonicalEncodingMap;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return singleton;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultEncodingMenus[] = {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_UTF16LE,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO88591,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_WINDOWS1252,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_GBK,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_GB18030,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_BIG5,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_BIG5HKSCS,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_KOREAN,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_SHIFTJIS,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_EUCJP,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO2022JP,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_THAI,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO885915,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_MACINTOSH,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO88592,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_WINDOWS1250,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO88595,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_WINDOWS1251,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_KOI8R,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_KOI8U,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO88597,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_WINDOWS1253,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_WINDOWS1254,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_WINDOWS1256,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO88596,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_WINDOWS1255,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO88598I,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO88598,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_WINDOWS1258,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO88594,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO885913,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_WINDOWS1257,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO88593,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO885910,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO885914,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDC_ENCODING_ISO885916,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultEncodingMenusLength = arraysize(kDefaultEncodingMenus);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parse the input |encoding_list| which is a encoding list separated with
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// comma, get available encoding ids and save them to |available_list|.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The parameter |maximum_size| indicates maximum size of encoding items we
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// want to get from the |encoding_list|.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ParseEncodingListSeparatedWithComma(
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& encoding_list, std::vector<int>* const available_list,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t maximum_size) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StringTokenizer tokenizer(encoding_list, ",");
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (tokenizer.GetNext()) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int id = CharacterEncoding::GetCommandIdByCanonicalEncodingName(
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tokenizer.token());
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ignore invalid encoding.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!id)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    available_list->push_back(id);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (available_list->size() == maximum_size)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 GetEncodingDisplayName(const std::string& encoding_name,
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      int category_string_id) {
255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 category_name = l10n_util::GetStringUTF16(category_string_id);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (category_string_id != IDS_ENCODING_KOREAN &&
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      category_string_id != IDS_ENCODING_THAI &&
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      category_string_id != IDS_ENCODING_TURKISH) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CanonicalNameDisplayNameMapType* map =
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CanonicalEncodingMapSingleton()->GetCanonicalNameDisplayNameMapData();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(map);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CanonicalNameDisplayNameMapType::const_iterator found_name =
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        map->find(encoding_name);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(found_name != map->end());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return l10n_util::GetStringFUTF16(IDS_ENCODING_DISPLAY_TEMPLATE,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      category_name,
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      base::ASCIIToUTF16(found_name->second));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return category_name;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GetEncodingCategoryStringIdByCommandId(int id) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const IdToCanonicalEncodingNameMapType* map =
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(map);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdToCanonicalEncodingNameMapType::const_iterator found_name = map->find(id);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found_name != map->end())
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return found_name->second.second;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetEncodingCategoryStringByCommandId(int id) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int category_id = GetEncodingCategoryStringIdByCommandId(id);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (category_id)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return l10n_util::GetStringUTF8(category_id);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CharacterEncoding::EncodingInfo::EncodingInfo(int id)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : encoding_id(id) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_category_name =
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF8ToUTF16(GetEncodingCategoryStringByCommandId(id));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoding_display_name = GetCanonicalEncodingDisplayNameByCommandId(id);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CharacterEncoding::GetCommandIdByCanonicalEncodingName(
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& encoding_name) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CanonicalEncodingNameToIdMapType* map =
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CanonicalEncodingMapSingleton()->GetCanonicalEncodingNameToIdMapData();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(map);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CanonicalEncodingNameToIdMapType::const_iterator found_id =
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      map->find(encoding_name);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found_id != map->end())
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return found_id->second;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CharacterEncoding::GetCanonicalEncodingNameByCommandId(int id) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const IdToCanonicalEncodingNameMapType* map =
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(map);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdToCanonicalEncodingNameMapType::const_iterator found_name = map->find(id);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found_name != map->end())
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return found_name->second.first;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 CharacterEncoding::GetCanonicalEncodingDisplayNameByCommandId(
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int id) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const IdToCanonicalEncodingNameMapType* map =
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(map);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdToCanonicalEncodingNameMapType::const_iterator found_name = map->find(id);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found_name != map->end())
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetEncodingDisplayName(found_name->second.first,
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  found_name->second.second);
337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return base::string16();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return count number of all supported canonical encoding.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CharacterEncoding::GetSupportCanonicalEncodingCount() {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kCanonicalEncodingNamesLength;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CharacterEncoding::GetCanonicalEncodingNameByIndex(int index) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index < kCanonicalEncodingNamesLength)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return kCanonicalEncodingNames[index].name;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 CharacterEncoding::GetCanonicalEncodingDisplayNameByIndex(
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index < kCanonicalEncodingNamesLength)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetEncodingDisplayName(kCanonicalEncodingNames[index].name,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kCanonicalEncodingNames[index].category_string_id);
359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return base::string16();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CharacterEncoding::GetEncodingCommandIdByIndex(int index) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index < kCanonicalEncodingNamesLength)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return kCanonicalEncodingNames[index].resource_id;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CharacterEncoding::GetCanonicalEncodingNameByAliasName(
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& alias_name) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the input alias_name is already canonical encoding name, just return it.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CanonicalEncodingNameToIdMapType* map =
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CanonicalEncodingMapSingleton()->GetCanonicalEncodingNameToIdMapData();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(map);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CanonicalEncodingNameToIdMapType::const_iterator found_id =
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      map->find(alias_name);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found_id != map->end())
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return alias_name;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UErrorCode error_code = U_ZERO_ERROR;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* canonical_name = ucnv_getCanonicalName(
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alias_name.c_str(), "MIME", &error_code);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If failed,  then try IANA next.
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (U_FAILURE(error_code) || !canonical_name) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_code = U_ZERO_ERROR;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canonical_name = ucnv_getCanonicalName(
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alias_name.c_str(), "IANA", &error_code);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (canonical_name) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(jnd) use a map to handle all customized {alias, canonical}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // encoding mappings if we have more than one pair.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't want to add an unnecessary charset to the encoding menu, so we
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // alias 'US-ASCII' to 'ISO-8859-1' in our UI without touching WebKit.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // http://crbug.com/15801.
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (alias_name == "US-ASCII")
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetCanonicalEncodingNameByCommandId(IDC_ENCODING_ISO88591);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return canonical_name;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string();
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// According to the behavior of user recently selected encoding short list in
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Firefox, we always put UTF-8 as top position, after then put user
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recent selected encodings, then put local dependent encoding items.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// At last, we put all remaining encoding items.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::vector<CharacterEncoding::EncodingInfo>*
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CharacterEncoding::GetCurrentDisplayEncodings(
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& locale,
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& locale_encodings,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& recently_select_encodings) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int>* const locale_dependent_encoding_list =
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CanonicalEncodingMapSingleton()->locale_dependent_encoding_ids();
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<CharacterEncoding::EncodingInfo>* const encoding_list =
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CanonicalEncodingMapSingleton()->current_display_encodings();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize locale dependent static encoding list.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (locale_dependent_encoding_list->empty() && !locale_encodings.empty())
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParseEncodingListSeparatedWithComma(locale_encodings,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        locale_dependent_encoding_list,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        kUserSelectedEncodingsMaxLength);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(std::string, cached_user_selected_encodings, ());
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build current display encoding list.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (encoding_list->empty() ||
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cached_user_selected_encodings != recently_select_encodings) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update user recently selected encodings.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cached_user_selected_encodings = recently_select_encodings;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clear old encoding list since user recently selected encodings changed.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encoding_list->clear();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Always add UTF-8 to first encoding position.
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encoding_list->push_back(EncodingInfo(IDC_ENCODING_UTF8));
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<int> inserted_encoding;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inserted_encoding.insert(IDC_ENCODING_UTF8);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Parse user recently selected encodings and get list
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<int> recently_select_encoding_list;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParseEncodingListSeparatedWithComma(recently_select_encodings,
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &recently_select_encoding_list,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        kUserSelectedEncodingsMaxLength);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Put 'cached encodings' (dynamic encoding list) after 'local dependent
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // encoding list'.
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    recently_select_encoding_list.insert(recently_select_encoding_list.begin(),
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        locale_dependent_encoding_list->begin(),
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        locale_dependent_encoding_list->end());
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<int>::iterator it = recently_select_encoding_list.begin();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != recently_select_encoding_list.end(); ++it) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Test whether we have met this encoding id.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool ok = inserted_encoding.insert(*it).second;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Duplicated encoding, ignore it. Ideally, this situation should not
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // happened, but just in case some one manually edit preference file.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!ok)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        encoding_list->push_back(EncodingInfo(*it));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Append a separator;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encoding_list->push_back(EncodingInfo(0));
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to keep "Unicode (UTF-16LE)" always at the top (among the rest
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of encodings) instead of being sorted along with other encodings. So if
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "Unicode (UTF-16LE)" is already in previous encodings, sort the rest
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of encodings. Otherwise Put "Unicode (UTF-16LE)" on the first of the
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // rest of encodings, skip "Unicode (UTF-16LE)" and sort all left encodings.
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int start_sorted_index = encoding_list->size();
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (inserted_encoding.find(IDC_ENCODING_UTF16LE) ==
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        inserted_encoding.end()) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      encoding_list->push_back(EncodingInfo(IDC_ENCODING_UTF16LE));
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inserted_encoding.insert(IDC_ENCODING_UTF16LE);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_sorted_index++;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add the rest of encodings that are neither in the static encoding list
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // nor in the list of recently selected encodings.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Build the encoding list sorted in the current locale sorting order.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kDefaultEncodingMenusLength; ++i) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int id = kDefaultEncodingMenus[i];
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We have inserted this encoding, skip it.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (inserted_encoding.find(id) != inserted_encoding.end())
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      encoding_list->push_back(EncodingInfo(id));
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sort the encoding list.
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l10n_util::SortVectorWithStringKey(locale,
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       encoding_list,
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       start_sorted_index,
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       encoding_list->size(),
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       true);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!encoding_list->empty());
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return encoding_list;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CharacterEncoding::UpdateRecentlySelectedEncoding(
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& original_selected_encodings,
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int new_selected_encoding_id,
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* selected_encodings) {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get encoding name.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string encoding_name =
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetCanonicalEncodingNameByCommandId(new_selected_encoding_id);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!encoding_name.empty());
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check whether the new encoding is in local dependent encodings or original
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // recently selected encodings. If yes, do not add it.
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int>* locale_dependent_encoding_list =
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CanonicalEncodingMapSingleton()->locale_dependent_encoding_ids();
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(locale_dependent_encoding_list);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> selected_encoding_list;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParseEncodingListSeparatedWithComma(original_selected_encodings,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      &selected_encoding_list,
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      kUserSelectedEncodingsMaxLength);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Put 'cached encodings' (dynamic encoding list) after 'local dependent
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // encoding list' for check.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> top_encoding_list(*locale_dependent_encoding_list);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UTF8 is always in our optimized encoding list.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_encoding_list.insert(top_encoding_list.begin(), IDC_ENCODING_UTF8);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_encoding_list.insert(top_encoding_list.end(),
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           selected_encoding_list.begin(),
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           selected_encoding_list.end());
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<int>::const_iterator it = top_encoding_list.begin();
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != top_encoding_list.end(); ++it)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*it == new_selected_encoding_id)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Need to add the encoding id to recently selected encoding list.
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the last encoding in original list.
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (selected_encoding_list.size() == kUserSelectedEncodingsMaxLength)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    selected_encoding_list.pop_back();
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Insert new encoding to head of selected encoding list.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *selected_encodings = encoding_name;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the string for rest selected encoding list.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<int>::const_iterator it = selected_encoding_list.begin();
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != selected_encoding_list.end(); ++it) {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    selected_encodings->append(1, L',');
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    selected_encodings->append(GetCanonicalEncodingNameByCommandId(*it));
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
543