1 // Copyright (c) 2011 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"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/string_tokenizer.h"
13 #include "base/string_util.h"
14 #include "base/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 "ui/base/l10n/l10n_util.h"
19 #include "ui/base/l10n/l10n_util_collator.h"
20 #include "unicode/ucnv.h"
22 using content::BrowserThread
;
26 // The maximum length of short list of recently user selected encodings is 3.
27 const size_t kUserSelectedEncodingsMaxLength
= 3;
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
, "windows-949", 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
;
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-949", "Windows-949" },
92 { "windows-1250", "Windows-1250" },
93 { "windows-1251", "Windows-1251" },
94 { "windows-1252", "Windows-1252" },
95 { "windows-1253", "Windows-1253" },
96 { "windows-1254", "Windows-1254" },
97 { "windows-1255", "Windows-1255" },
98 { "windows-1256", "Windows-1256" },
99 { "windows-1257", "Windows-1257" },
100 { "windows-1258", "Windows-1258" },
103 const int kCanonicalDisplayNameOverridesLength
=
104 arraysize(kCanonicalDisplayNameOverrides
);
106 typedef std::map
<std::string
, const char*> CanonicalNameDisplayNameMapType
;
108 class CanonicalEncodingMap
{
110 CanonicalEncodingMap()
111 : id_to_encoding_name_map_(NULL
),
112 encoding_name_to_id_map_(NULL
),
113 encoding_name_to_display_name_map_(NULL
) { }
114 const IdToCanonicalEncodingNameMapType
* GetIdToCanonicalEncodingNameMapData();
115 const CanonicalEncodingNameToIdMapType
* GetCanonicalEncodingNameToIdMapData();
116 const CanonicalNameDisplayNameMapType
* GetCanonicalNameDisplayNameMapData();
117 std::vector
<int>* locale_dependent_encoding_ids() {
118 return &locale_dependent_encoding_ids_
;
121 std::vector
<CharacterEncoding::EncodingInfo
>* current_display_encodings() {
122 return ¤t_display_encodings_
;
126 scoped_ptr
<IdToCanonicalEncodingNameMapType
> id_to_encoding_name_map_
;
127 scoped_ptr
<CanonicalEncodingNameToIdMapType
> encoding_name_to_id_map_
;
128 scoped_ptr
<CanonicalNameDisplayNameMapType
>
129 encoding_name_to_display_name_map_
;
130 std::vector
<int> locale_dependent_encoding_ids_
;
131 std::vector
<CharacterEncoding::EncodingInfo
> current_display_encodings_
;
133 DISALLOW_COPY_AND_ASSIGN(CanonicalEncodingMap
);
136 const IdToCanonicalEncodingNameMapType
*
137 CanonicalEncodingMap::GetIdToCanonicalEncodingNameMapData() {
138 // Testing and building map is not thread safe, this function is supposed to
139 // only run in UI thread. Myabe I should add a lock in here for making it as
141 if (!id_to_encoding_name_map_
.get()) {
142 id_to_encoding_name_map_
.reset(new IdToCanonicalEncodingNameMapType
);
143 for (int i
= 0; i
< kCanonicalEncodingNamesLength
; ++i
) {
144 int resource_id
= kCanonicalEncodingNames
[i
].resource_id
;
145 (*id_to_encoding_name_map_
)[resource_id
] =
146 std::make_pair(kCanonicalEncodingNames
[i
].name
,
147 kCanonicalEncodingNames
[i
].category_string_id
);
150 return id_to_encoding_name_map_
.get();
153 const CanonicalEncodingNameToIdMapType
*
154 CanonicalEncodingMap::GetCanonicalEncodingNameToIdMapData() {
155 if (!encoding_name_to_id_map_
.get()) {
156 encoding_name_to_id_map_
.reset(new CanonicalEncodingNameToIdMapType
);
157 for (int i
= 0; i
< kCanonicalEncodingNamesLength
; ++i
) {
158 (*encoding_name_to_id_map_
)[kCanonicalEncodingNames
[i
].name
] =
159 kCanonicalEncodingNames
[i
].resource_id
;
162 return encoding_name_to_id_map_
.get();
165 const CanonicalNameDisplayNameMapType
*
166 CanonicalEncodingMap::GetCanonicalNameDisplayNameMapData() {
167 if (!encoding_name_to_display_name_map_
.get()) {
168 encoding_name_to_display_name_map_
.reset(
169 new CanonicalNameDisplayNameMapType
);
170 // First store the names in the kCanonicalEncodingNames list.
171 for (int i
= 0; i
< kCanonicalEncodingNamesLength
; ++i
) {
172 (*encoding_name_to_display_name_map_
)[kCanonicalEncodingNames
[i
].name
] =
173 kCanonicalEncodingNames
[i
].name
;
175 // Then save in the overrides.
176 for (int i
= 0; i
< kCanonicalDisplayNameOverridesLength
; ++i
) {
177 (*encoding_name_to_display_name_map_
)
178 [kCanonicalDisplayNameOverrides
[i
].canonical_form
] =
179 kCanonicalDisplayNameOverrides
[i
].display_form
;
181 DCHECK(static_cast<int>(encoding_name_to_display_name_map_
->size()) ==
182 kCanonicalEncodingNamesLength
)
183 << "Got an override that wasn't in the encoding list";
185 return encoding_name_to_display_name_map_
.get();
188 // A static map object which contains all resourceid-nonsequenced canonical
190 CanonicalEncodingMap
* CanonicalEncodingMapSingleton() {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
192 static CanonicalEncodingMap
* singleton
= new CanonicalEncodingMap
;
196 const int kDefaultEncodingMenus
[] = {
197 IDC_ENCODING_UTF16LE
,
198 IDC_ENCODING_ISO88591
,
199 IDC_ENCODING_WINDOWS1252
,
201 IDC_ENCODING_GB18030
,
203 IDC_ENCODING_BIG5HKSCS
,
205 IDC_ENCODING_SHIFTJIS
,
207 IDC_ENCODING_ISO2022JP
,
209 IDC_ENCODING_ISO885915
,
210 IDC_ENCODING_MACINTOSH
,
211 IDC_ENCODING_ISO88592
,
212 IDC_ENCODING_WINDOWS1250
,
213 IDC_ENCODING_ISO88595
,
214 IDC_ENCODING_WINDOWS1251
,
217 IDC_ENCODING_ISO88597
,
218 IDC_ENCODING_WINDOWS1253
,
219 IDC_ENCODING_WINDOWS1254
,
220 IDC_ENCODING_WINDOWS1256
,
221 IDC_ENCODING_ISO88596
,
222 IDC_ENCODING_WINDOWS1255
,
223 IDC_ENCODING_ISO88598I
,
224 IDC_ENCODING_ISO88598
,
225 IDC_ENCODING_WINDOWS1258
,
226 IDC_ENCODING_ISO88594
,
227 IDC_ENCODING_ISO885913
,
228 IDC_ENCODING_WINDOWS1257
,
229 IDC_ENCODING_ISO88593
,
230 IDC_ENCODING_ISO885910
,
231 IDC_ENCODING_ISO885914
,
232 IDC_ENCODING_ISO885916
,
235 const int kDefaultEncodingMenusLength
= arraysize(kDefaultEncodingMenus
);
237 // Parse the input |encoding_list| which is a encoding list separated with
238 // comma, get available encoding ids and save them to |available_list|.
239 // The parameter |maximum_size| indicates maximum size of encoding items we
240 // want to get from the |encoding_list|.
241 void ParseEncodingListSeparatedWithComma(
242 const std::string
& encoding_list
, std::vector
<int>* const available_list
,
243 size_t maximum_size
) {
244 StringTokenizer
tokenizer(encoding_list
, ",");
245 while (tokenizer
.GetNext()) {
246 int id
= CharacterEncoding::GetCommandIdByCanonicalEncodingName(
248 // Ignore invalid encoding.
251 available_list
->push_back(id
);
252 if (available_list
->size() == maximum_size
)
257 string16
GetEncodingDisplayName(std::string encoding_name
,
258 int category_string_id
) {
259 string16 category_name
= l10n_util::GetStringUTF16(category_string_id
);
260 if (category_string_id
!= IDS_ENCODING_KOREAN
&&
261 category_string_id
!= IDS_ENCODING_THAI
&&
262 category_string_id
!= IDS_ENCODING_TURKISH
) {
263 const CanonicalNameDisplayNameMapType
* map
=
264 CanonicalEncodingMapSingleton()->GetCanonicalNameDisplayNameMapData();
267 CanonicalNameDisplayNameMapType::const_iterator found_name
=
268 map
->find(encoding_name
);
269 DCHECK(found_name
!= map
->end());
270 return l10n_util::GetStringFUTF16(IDS_ENCODING_DISPLAY_TEMPLATE
,
272 ASCIIToUTF16(found_name
->second
));
274 return category_name
;
277 int GetEncodingCategoryStringIdByCommandId(int id
) {
278 const IdToCanonicalEncodingNameMapType
* map
=
279 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
282 IdToCanonicalEncodingNameMapType::const_iterator found_name
= map
->find(id
);
283 if (found_name
!= map
->end())
284 return found_name
->second
.second
;
288 std::string
GetEncodingCategoryStringByCommandId(int id
) {
289 int category_id
= GetEncodingCategoryStringIdByCommandId(id
);
291 return l10n_util::GetStringUTF8(category_id
);
292 return std::string();
297 CharacterEncoding::EncodingInfo::EncodingInfo(int id
)
299 encoding_category_name
=
300 UTF8ToUTF16(GetEncodingCategoryStringByCommandId(id
));
301 encoding_display_name
= GetCanonicalEncodingDisplayNameByCommandId(id
);
305 int CharacterEncoding::GetCommandIdByCanonicalEncodingName(
306 const std::string
& encoding_name
) {
307 const CanonicalEncodingNameToIdMapType
* map
=
308 CanonicalEncodingMapSingleton()->GetCanonicalEncodingNameToIdMapData();
311 CanonicalEncodingNameToIdMapType::const_iterator found_id
=
312 map
->find(encoding_name
);
313 if (found_id
!= map
->end())
314 return found_id
->second
;
319 std::string
CharacterEncoding::GetCanonicalEncodingNameByCommandId(int id
) {
320 const IdToCanonicalEncodingNameMapType
* map
=
321 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
324 IdToCanonicalEncodingNameMapType::const_iterator found_name
= map
->find(id
);
325 if (found_name
!= map
->end())
326 return found_name
->second
.first
;
327 return std::string();
331 string16
CharacterEncoding::GetCanonicalEncodingDisplayNameByCommandId(
333 const IdToCanonicalEncodingNameMapType
* map
=
334 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
337 IdToCanonicalEncodingNameMapType::const_iterator found_name
= map
->find(id
);
338 if (found_name
!= map
->end())
339 return GetEncodingDisplayName(found_name
->second
.first
,
340 found_name
->second
.second
);
345 // Return count number of all supported canonical encoding.
346 int CharacterEncoding::GetSupportCanonicalEncodingCount() {
347 return kCanonicalEncodingNamesLength
;
351 std::string
CharacterEncoding::GetCanonicalEncodingNameByIndex(int index
) {
352 if (index
< kCanonicalEncodingNamesLength
)
353 return kCanonicalEncodingNames
[index
].name
;
354 return std::string();
358 string16
CharacterEncoding::GetCanonicalEncodingDisplayNameByIndex(
360 if (index
< kCanonicalEncodingNamesLength
)
361 return GetEncodingDisplayName(kCanonicalEncodingNames
[index
].name
,
362 kCanonicalEncodingNames
[index
].category_string_id
);
367 int CharacterEncoding::GetEncodingCommandIdByIndex(int index
) {
368 if (index
< kCanonicalEncodingNamesLength
)
369 return kCanonicalEncodingNames
[index
].resource_id
;
374 std::string
CharacterEncoding::GetCanonicalEncodingNameByAliasName(
375 const std::string
& alias_name
) {
376 // If the input alias_name is already canonical encoding name, just return it.
377 const CanonicalEncodingNameToIdMapType
* map
=
378 CanonicalEncodingMapSingleton()->GetCanonicalEncodingNameToIdMapData();
381 CanonicalEncodingNameToIdMapType::const_iterator found_id
=
382 map
->find(alias_name
);
383 if (found_id
!= map
->end())
386 UErrorCode error_code
= U_ZERO_ERROR
;
388 const char* canonical_name
= ucnv_getCanonicalName(
389 alias_name
.c_str(), "MIME", &error_code
);
390 // If failed, then try IANA next.
391 if (U_FAILURE(error_code
) || !canonical_name
) {
392 error_code
= U_ZERO_ERROR
;
393 canonical_name
= ucnv_getCanonicalName(
394 alias_name
.c_str(), "IANA", &error_code
);
397 if (canonical_name
) {
398 // TODO(jnd) use a map to handle all customized {alias, canonical}
399 // encoding mappings if we have more than one pair.
400 // We don't want to add an unnecessary charset to the encoding menu, so we
401 // alias 'US-ASCII' to 'ISO-8859-1' in our UI without touching WebKit.
402 // http://crbug.com/15801.
403 if (alias_name
== "US-ASCII")
404 return GetCanonicalEncodingNameByCommandId(IDC_ENCODING_ISO88591
);
405 return canonical_name
;
407 return std::string();
412 // According to the behavior of user recently selected encoding short list in
413 // Firefox, we always put UTF-8 as top position, after then put user
414 // recent selected encodings, then put local dependent encoding items.
415 // At last, we put all remaining encoding items.
416 const std::vector
<CharacterEncoding::EncodingInfo
>*
417 CharacterEncoding::GetCurrentDisplayEncodings(
418 const std::string
& locale
,
419 const std::string
& locale_encodings
,
420 const std::string
& recently_select_encodings
) {
421 std::vector
<int>* const locale_dependent_encoding_list
=
422 CanonicalEncodingMapSingleton()->locale_dependent_encoding_ids();
423 std::vector
<CharacterEncoding::EncodingInfo
>* const encoding_list
=
424 CanonicalEncodingMapSingleton()->current_display_encodings();
426 // Initialize locale dependent static encoding list.
427 if (locale_dependent_encoding_list
->empty() && !locale_encodings
.empty())
428 ParseEncodingListSeparatedWithComma(locale_encodings
,
429 locale_dependent_encoding_list
,
430 kUserSelectedEncodingsMaxLength
);
432 CR_DEFINE_STATIC_LOCAL(std::string
, cached_user_selected_encodings
, ());
433 // Build current display encoding list.
434 if (encoding_list
->empty() ||
435 cached_user_selected_encodings
!= recently_select_encodings
) {
436 // Update user recently selected encodings.
437 cached_user_selected_encodings
= recently_select_encodings
;
438 // Clear old encoding list since user recently selected encodings changed.
439 encoding_list
->clear();
440 // Always add UTF-8 to first encoding position.
441 encoding_list
->push_back(EncodingInfo(IDC_ENCODING_UTF8
));
442 std::set
<int> inserted_encoding
;
443 inserted_encoding
.insert(IDC_ENCODING_UTF8
);
445 // Parse user recently selected encodings and get list
446 std::vector
<int> recently_select_encoding_list
;
447 ParseEncodingListSeparatedWithComma(recently_select_encodings
,
448 &recently_select_encoding_list
,
449 kUserSelectedEncodingsMaxLength
);
451 // Put 'cached encodings' (dynamic encoding list) after 'local dependent
453 recently_select_encoding_list
.insert(recently_select_encoding_list
.begin(),
454 locale_dependent_encoding_list
->begin(),
455 locale_dependent_encoding_list
->end());
456 for (std::vector
<int>::iterator it
= recently_select_encoding_list
.begin();
457 it
!= recently_select_encoding_list
.end(); ++it
) {
458 // Test whether we have met this encoding id.
459 bool ok
= inserted_encoding
.insert(*it
).second
;
460 // Duplicated encoding, ignore it. Ideally, this situation should not
461 // happened, but just in case some one manually edit preference file.
464 encoding_list
->push_back(EncodingInfo(*it
));
466 // Append a separator;
467 encoding_list
->push_back(EncodingInfo(0));
469 // We need to keep "Unicode (UTF-16LE)" always at the top (among the rest
470 // of encodings) instead of being sorted along with other encodings. So if
471 // "Unicode (UTF-16LE)" is already in previous encodings, sort the rest
472 // of encodings. Otherwise Put "Unicode (UTF-16LE)" on the first of the
473 // rest of encodings, skip "Unicode (UTF-16LE)" and sort all left encodings.
474 int start_sorted_index
= encoding_list
->size();
475 if (inserted_encoding
.find(IDC_ENCODING_UTF16LE
) ==
476 inserted_encoding
.end()) {
477 encoding_list
->push_back(EncodingInfo(IDC_ENCODING_UTF16LE
));
478 inserted_encoding
.insert(IDC_ENCODING_UTF16LE
);
479 start_sorted_index
++;
482 // Add the rest of encodings that are neither in the static encoding list
483 // nor in the list of recently selected encodings.
484 // Build the encoding list sorted in the current locale sorting order.
485 for (int i
= 0; i
< kDefaultEncodingMenusLength
; ++i
) {
486 int id
= kDefaultEncodingMenus
[i
];
487 // We have inserted this encoding, skip it.
488 if (inserted_encoding
.find(id
) != inserted_encoding
.end())
490 encoding_list
->push_back(EncodingInfo(id
));
492 // Sort the encoding list.
493 l10n_util::SortVectorWithStringKey(locale
,
496 encoding_list
->size(),
499 DCHECK(!encoding_list
->empty());
500 return encoding_list
;
504 bool CharacterEncoding::UpdateRecentlySelectedEncoding(
505 const std::string
& original_selected_encodings
,
506 int new_selected_encoding_id
,
507 std::string
* selected_encodings
) {
508 // Get encoding name.
509 std::string encoding_name
=
510 GetCanonicalEncodingNameByCommandId(new_selected_encoding_id
);
511 DCHECK(!encoding_name
.empty());
512 // Check whether the new encoding is in local dependent encodings or original
513 // recently selected encodings. If yes, do not add it.
514 std::vector
<int>* locale_dependent_encoding_list
=
515 CanonicalEncodingMapSingleton()->locale_dependent_encoding_ids();
516 DCHECK(locale_dependent_encoding_list
);
517 std::vector
<int> selected_encoding_list
;
518 ParseEncodingListSeparatedWithComma(original_selected_encodings
,
519 &selected_encoding_list
,
520 kUserSelectedEncodingsMaxLength
);
521 // Put 'cached encodings' (dynamic encoding list) after 'local dependent
522 // encoding list' for check.
523 std::vector
<int> top_encoding_list(*locale_dependent_encoding_list
);
524 // UTF8 is always in our optimized encoding list.
525 top_encoding_list
.insert(top_encoding_list
.begin(), IDC_ENCODING_UTF8
);
526 top_encoding_list
.insert(top_encoding_list
.end(),
527 selected_encoding_list
.begin(),
528 selected_encoding_list
.end());
529 for (std::vector
<int>::const_iterator it
= top_encoding_list
.begin();
530 it
!= top_encoding_list
.end(); ++it
)
531 if (*it
== new_selected_encoding_id
)
533 // Need to add the encoding id to recently selected encoding list.
534 // Remove the last encoding in original list.
535 if (selected_encoding_list
.size() == kUserSelectedEncodingsMaxLength
)
536 selected_encoding_list
.pop_back();
537 // Insert new encoding to head of selected encoding list.
538 *selected_encodings
= encoding_name
;
539 // Generate the string for rest selected encoding list.
540 for (std::vector
<int>::const_iterator it
= selected_encoding_list
.begin();
541 it
!= selected_encoding_list
.end(); ++it
) {
542 selected_encodings
->append(1, L
',');
543 selected_encodings
->append(GetCanonicalEncodingNameByCommandId(*it
));