Return backed up TemplateURL on default search change
[chromium-blink-merge.git] / chrome / browser / character_encoding.cc
blob460da9ef127e54e451200dab684eed06857217f7
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"
7 #include <map>
8 #include <set>
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;
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, "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;
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-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 {
109 public:
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 &current_display_encodings_;
125 private:
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
140 // thread safe.
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
189 // encoding names.
190 CanonicalEncodingMap* CanonicalEncodingMapSingleton() {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
192 static CanonicalEncodingMap* singleton = new CanonicalEncodingMap;
193 return singleton;
196 const int kDefaultEncodingMenus[] = {
197 IDC_ENCODING_UTF16LE,
198 IDC_ENCODING_ISO88591,
199 IDC_ENCODING_WINDOWS1252,
200 IDC_ENCODING_GBK,
201 IDC_ENCODING_GB18030,
202 IDC_ENCODING_BIG5,
203 IDC_ENCODING_BIG5HKSCS,
204 IDC_ENCODING_KOREAN,
205 IDC_ENCODING_SHIFTJIS,
206 IDC_ENCODING_EUCJP,
207 IDC_ENCODING_ISO2022JP,
208 IDC_ENCODING_THAI,
209 IDC_ENCODING_ISO885915,
210 IDC_ENCODING_MACINTOSH,
211 IDC_ENCODING_ISO88592,
212 IDC_ENCODING_WINDOWS1250,
213 IDC_ENCODING_ISO88595,
214 IDC_ENCODING_WINDOWS1251,
215 IDC_ENCODING_KOI8R,
216 IDC_ENCODING_KOI8U,
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(
247 tokenizer.token());
248 // Ignore invalid encoding.
249 if (!id)
250 continue;
251 available_list->push_back(id);
252 if (available_list->size() == maximum_size)
253 return;
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();
265 DCHECK(map);
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,
271 category_name,
272 ASCIIToUTF16(found_name->second));
274 return category_name;
277 int GetEncodingCategoryStringIdByCommandId(int id) {
278 const IdToCanonicalEncodingNameMapType* map =
279 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
280 DCHECK(map);
282 IdToCanonicalEncodingNameMapType::const_iterator found_name = map->find(id);
283 if (found_name != map->end())
284 return found_name->second.second;
285 return 0;
288 std::string GetEncodingCategoryStringByCommandId(int id) {
289 int category_id = GetEncodingCategoryStringIdByCommandId(id);
290 if (category_id)
291 return l10n_util::GetStringUTF8(category_id);
292 return std::string();
295 } // namespace
297 CharacterEncoding::EncodingInfo::EncodingInfo(int id)
298 : encoding_id(id) {
299 encoding_category_name =
300 UTF8ToUTF16(GetEncodingCategoryStringByCommandId(id));
301 encoding_display_name = GetCanonicalEncodingDisplayNameByCommandId(id);
304 // Static.
305 int CharacterEncoding::GetCommandIdByCanonicalEncodingName(
306 const std::string& encoding_name) {
307 const CanonicalEncodingNameToIdMapType* map =
308 CanonicalEncodingMapSingleton()->GetCanonicalEncodingNameToIdMapData();
309 DCHECK(map);
311 CanonicalEncodingNameToIdMapType::const_iterator found_id =
312 map->find(encoding_name);
313 if (found_id != map->end())
314 return found_id->second;
315 return 0;
318 // Static.
319 std::string CharacterEncoding::GetCanonicalEncodingNameByCommandId(int id) {
320 const IdToCanonicalEncodingNameMapType* map =
321 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
322 DCHECK(map);
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();
330 // Static.
331 string16 CharacterEncoding::GetCanonicalEncodingDisplayNameByCommandId(
332 int id) {
333 const IdToCanonicalEncodingNameMapType* map =
334 CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
335 DCHECK(map);
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);
341 return string16();
344 // Static.
345 // Return count number of all supported canonical encoding.
346 int CharacterEncoding::GetSupportCanonicalEncodingCount() {
347 return kCanonicalEncodingNamesLength;
350 // Static.
351 std::string CharacterEncoding::GetCanonicalEncodingNameByIndex(int index) {
352 if (index < kCanonicalEncodingNamesLength)
353 return kCanonicalEncodingNames[index].name;
354 return std::string();
357 // Static.
358 string16 CharacterEncoding::GetCanonicalEncodingDisplayNameByIndex(
359 int index) {
360 if (index < kCanonicalEncodingNamesLength)
361 return GetEncodingDisplayName(kCanonicalEncodingNames[index].name,
362 kCanonicalEncodingNames[index].category_string_id);
363 return string16();
366 // Static.
367 int CharacterEncoding::GetEncodingCommandIdByIndex(int index) {
368 if (index < kCanonicalEncodingNamesLength)
369 return kCanonicalEncodingNames[index].resource_id;
370 return 0;
373 // Static.
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();
379 DCHECK(map);
381 CanonicalEncodingNameToIdMapType::const_iterator found_id =
382 map->find(alias_name);
383 if (found_id != map->end())
384 return alias_name;
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;
406 } else {
407 return std::string();
411 // Static
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
452 // encoding list'.
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.
462 if (!ok)
463 continue;
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())
489 continue;
490 encoding_list->push_back(EncodingInfo(id));
492 // Sort the encoding list.
493 l10n_util::SortVectorWithStringKey(locale,
494 encoding_list,
495 start_sorted_index,
496 encoding_list->size(),
497 true);
499 DCHECK(!encoding_list->empty());
500 return encoding_list;
503 // Static
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)
532 return false;
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));
545 return true;