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"
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
;
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
, "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
;
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
{
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 ¤t_display_encodings_
;
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
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
186 CanonicalEncodingMap
* CanonicalEncodingMapSingleton() {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
188 static CanonicalEncodingMap
* singleton
= new CanonicalEncodingMap
;
192 const int kDefaultEncodingMenus
[] = {
193 IDC_ENCODING_UTF16LE
,
194 IDC_ENCODING_ISO88591
,
195 IDC_ENCODING_WINDOWS1252
,
197 IDC_ENCODING_GB18030
,
199 IDC_ENCODING_BIG5HKSCS
,
201 IDC_ENCODING_SHIFTJIS
,
203 IDC_ENCODING_ISO2022JP
,
205 IDC_ENCODING_ISO885915
,
206 IDC_ENCODING_MACINTOSH
,
207 IDC_ENCODING_ISO88592
,
208 IDC_ENCODING_WINDOWS1250
,
209 IDC_ENCODING_ISO88595
,
210 IDC_ENCODING_WINDOWS1251
,
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(
244 // Ignore invalid encoding.
247 available_list
->push_back(id
);
248 if (available_list
->size() == maximum_size
)
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();
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
,
268 base::ASCIIToUTF16(found_name
->second
));
270 return category_name
;
273 int GetEncodingCategoryStringIdByCommandId(int id
) {
274 const IdToCanonicalEncodingNameMapType
* map
=
275 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
278 IdToCanonicalEncodingNameMapType::const_iterator found_name
= map
->find(id
);
279 if (found_name
!= map
->end())
280 return found_name
->second
.second
;
284 std::string
GetEncodingCategoryStringByCommandId(int id
) {
285 int category_id
= GetEncodingCategoryStringIdByCommandId(id
);
287 return l10n_util::GetStringUTF8(category_id
);
288 return std::string();
293 CharacterEncoding::EncodingInfo::EncodingInfo(int id
)
295 encoding_category_name
=
296 base::UTF8ToUTF16(GetEncodingCategoryStringByCommandId(id
));
297 encoding_display_name
= GetCanonicalEncodingDisplayNameByCommandId(id
);
301 int CharacterEncoding::GetCommandIdByCanonicalEncodingName(
302 const std::string
& encoding_name
) {
303 const CanonicalEncodingNameToIdMapType
* map
=
304 CanonicalEncodingMapSingleton()->GetCanonicalEncodingNameToIdMapData();
307 CanonicalEncodingNameToIdMapType::const_iterator found_id
=
308 map
->find(encoding_name
);
309 if (found_id
!= map
->end())
310 return found_id
->second
;
315 std::string
CharacterEncoding::GetCanonicalEncodingNameByCommandId(int id
) {
316 const IdToCanonicalEncodingNameMapType
* map
=
317 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
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();
327 base::string16
CharacterEncoding::GetCanonicalEncodingDisplayNameByCommandId(
329 const IdToCanonicalEncodingNameMapType
* map
=
330 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
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();
341 // Return count number of all supported canonical encoding.
342 int CharacterEncoding::GetSupportCanonicalEncodingCount() {
343 return kCanonicalEncodingNamesLength
;
347 std::string
CharacterEncoding::GetCanonicalEncodingNameByIndex(int index
) {
348 if (index
< kCanonicalEncodingNamesLength
)
349 return kCanonicalEncodingNames
[index
].name
;
350 return std::string();
354 base::string16
CharacterEncoding::GetCanonicalEncodingDisplayNameByIndex(
356 if (index
< kCanonicalEncodingNamesLength
)
357 return GetEncodingDisplayName(kCanonicalEncodingNames
[index
].name
,
358 kCanonicalEncodingNames
[index
].category_string_id
);
359 return base::string16();
363 int CharacterEncoding::GetEncodingCommandIdByIndex(int index
) {
364 if (index
< kCanonicalEncodingNamesLength
)
365 return kCanonicalEncodingNames
[index
].resource_id
;
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();
377 CanonicalEncodingNameToIdMapType::const_iterator found_id
=
378 map
->find(alias_name
);
379 if (found_id
!= map
->end())
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
;
403 return std::string();
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
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.
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())
486 encoding_list
->push_back(EncodingInfo(id
));
488 // Sort the encoding list.
489 l10n_util::SortVectorWithStringKey(locale
,
492 encoding_list
->size(),
495 DCHECK(!encoding_list
->empty());
496 return encoding_list
;
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
)
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
));