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