Skip to content

Instantly share code, notes, and snippets.

@msr-i386
Last active December 20, 2016 13:20
Show Gist options
  • Save msr-i386/91897199b8600a9841ea8057a2082736 to your computer and use it in GitHub Desktop.
Save msr-i386/91897199b8600a9841ea8057a2082736 to your computer and use it in GitHub Desktop.
Chromium 55で削除されたエンコーディングメニューを復活させるパッチ
commit 6a39e99e5cca4bdccba49f2dbc5c32992f482c8b
Author: MSR <[email protected]>
Date: Tue Dec 20 20:32:23 2016 +0900
Restore encoding menu.
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index c634b10..5b8220c 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -85,6 +85,7 @@
#define IDC_VIEW_SOURCE 35002
#define IDC_PRINT 35003
#define IDC_SAVE_PAGE 35004
+#define IDC_ENCODING_MENU 35005
#define IDC_EMAIL_PAGE_LOCATION 35006
#define IDC_BASIC_PRINT 35007
#define IDC_SAVE_CREDIT_CARD_FOR_PAGE 35008
@@ -92,6 +100,47 @@
#define IDC_MANAGE_PASSWORDS_FOR_PAGE 35010
#define IDC_ROUTE_MEDIA 35011
+// When adding a new encoding to this list, be sure to append it to the
+// EncodingMenuController::kValidEncodingIds array in
+// encoding_menu_controller.cc.
+#define IDC_ENCODING_AUTO_DETECT 35500
+#define IDC_ENCODING_UTF8 35501
+#define IDC_ENCODING_UTF16LE 35502
+#define IDC_ENCODING_WINDOWS1252 35503
+#define IDC_ENCODING_GBK 35504
+#define IDC_ENCODING_GB18030 35505
+#define IDC_ENCODING_BIG5 35506
+#define IDC_ENCODING_KOREAN 35507
+#define IDC_ENCODING_SHIFTJIS 35508
+#define IDC_ENCODING_ISO2022JP 35509
+#define IDC_ENCODING_EUCJP 35510
+#define IDC_ENCODING_THAI 35511
+#define IDC_ENCODING_ISO885915 35512
+#define IDC_ENCODING_MACINTOSH 35513
+#define IDC_ENCODING_ISO88592 35514
+#define IDC_ENCODING_WINDOWS1250 35515
+#define IDC_ENCODING_ISO88595 35516
+#define IDC_ENCODING_WINDOWS1251 35517
+#define IDC_ENCODING_KOI8R 35518
+#define IDC_ENCODING_KOI8U 35519
+#define IDC_ENCODING_ISO88597 35520
+#define IDC_ENCODING_WINDOWS1253 35521
+#define IDC_ENCODING_ISO88594 35522
+#define IDC_ENCODING_ISO885913 35523
+#define IDC_ENCODING_WINDOWS1257 35524
+#define IDC_ENCODING_ISO88593 35525
+#define IDC_ENCODING_ISO885910 35526
+#define IDC_ENCODING_ISO885914 35527
+#define IDC_ENCODING_ISO885916 35528
+#define IDC_ENCODING_WINDOWS1254 35529
+#define IDC_ENCODING_ISO88596 35530
+#define IDC_ENCODING_WINDOWS1256 35531
+#define IDC_ENCODING_ISO88598 35532
+#define IDC_ENCODING_WINDOWS1255 35533
+#define IDC_ENCODING_WINDOWS1258 35534
+#define IDC_ENCODING_ISO88598I 35535
+#define IDC_ENCODING_IBM866 35536
+
// Clipboard commands
#define IDC_CUT 36000
#define IDC_COPY 36001
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 8ac8614..e45a812 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -1106,6 +1106,12 @@ are declared in build/common.gypi.
<message name="IDS_ZOOM_MINUS2" desc="The text label of the Make Text Smaller menu item in the merged menu">
&#8722;
</message>
+ <message name="IDS_ENCODING_MENU" desc="The text label of the Encoding submenu">
+ &amp;Encoding
+ </message>
+ <message name="IDS_ENCODING_AUTO_DETECT" desc="The text label of the Auto Detect submenu">
+ Auto detect
+ </message>
</if>
<if expr="use_titlecase">
<message name="IDS_NEW_TAB" desc="In Title Case: The text label of a menu item for opening a new tab">
@@ -1171,6 +1179,12 @@ are declared in build/common.gypi.
<message name="IDS_ZOOM_MINUS2" desc="The text label of the Make Text Smaller menu item in the merged menu">
&#8722;
</message>
+ <message name="IDS_ENCODING_MENU" desc="In Title Case: The text label of the Encoding submenu">
+ &amp;Encoding
+ </message>
+ <message name="IDS_ENCODING_AUTO_DETECT" desc="In Title Case: The text label of the Auto Detect submenu">
+ Auto Detect
+ </message>
</if>
</if>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb
index daa8653..d561ff1 100644
--- a/chrome/app/resources/generated_resources_ja.xtb
+++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -6167,4 +6167,6 @@
<translation id="996250603853062861">安全な接続を確立しています...</translation>
<translation id="996987097147224996">以前の入力方式を選択するには、Ctrl+ スペース キーを押します。</translation>
<translation id="998747458861718449">検証(&amp;I)</translation>
+<translation id="8434177709403049435">エンコード(&amp;E)</translation>
+<translation id="569109051430110155">自動検出</translation>
</translationbundle>
\ No newline at end of file
diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd
index 9c30065..7923901 100644
--- a/chrome/app/resources/locale_settings.grd
+++ b/chrome/app/resources/locale_settings.grd
@@ -131,6 +131,11 @@
<release seq="1" allow_pseudo="false">
<messages fallback_to_english="true">
+ <!-- The default value for |WebPreference::uses_universal_detector|. -->
+ <message name="IDS_USES_UNIVERSAL_DETECTOR" use_name_for_id="true">
+ true
+ </message>
+
<!-- The file name of the spellchecking dictionary without the extension (case-sensitive). -->
<message name="IDS_SPELLCHECK_DICTIONARY" use_name_for_id="true">
en-US
@@ -202,6 +207,11 @@
8
</message>
+ <!-- Locale-dependent static encodings string -->
+ <message name="IDS_STATIC_ENCODING_LIST" use_name_for_id="true">
+ windows-1252
+ </message>
+
<!-- The URL for the the Welcome to Chrome page shown on first run. -->
<message name="IDS_WELCOME_PAGE_URL" translateable="false">
http://tools.google.com/chrome/intl/[GRITLANGCODE]/welcome.html
diff --git a/chrome/app/resources/locale_settings_ja.xtb b/chrome/app/resources/locale_settings_ja.xtb
index 8f47dfc..8366e3a 100644
--- a/chrome/app/resources/locale_settings_ja.xtb
+++ b/chrome/app/resources/locale_settings_ja.xtb
@@ -1,6 +1,7 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ja">
+<translation id="IDS_USES_UNIVERSAL_DETECTOR">true</translation>
<translation id="IDS_SPELLCHECK_DICTIONARY">en-US</translation>
<translation id="IDS_SYSTEM_TRAY_MENU_BUBBLE_WIDTH_PIXELS">350</translation>
<translation id="IDS_OPTIONS_DIALOG_LEFT_COLUMN_WIDTH_CHARS">25</translation>
diff --git a/chrome/browser/character_encoding.cc b/chrome/browser/character_encoding.cc
index 2d4b059..b7c9f6f 100644
--- a/chrome/browser/character_encoding.cc
+++ b/chrome/browser/character_encoding.cc
@@ -4,57 +4,384 @@
#include "chrome/browser/character_encoding.h"
+#include <stddef.h>
+
+#include <map>
+#include <memory>
+#include <set>
+
+#include "base/logging.h"
#include "base/macros.h"
+#include "base/strings/string_tokenizer.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/browser_thread.h"
#include "third_party/icu/source/common/unicode/ucnv.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_collator.h"
+
+using content::BrowserThread;
namespace {
+// The maximum length of short list of recently user selected encodings is 3.
+const size_t kUserSelectedEncodingsMaxLength = 3;
+
+typedef struct {
+ int resource_id;
+ const char* name;
+ int category_string_id;
+} CanonicalEncodingData;
+
// An array of all supported canonical encoding names.
-const char* const kCanonicalEncodingNames[] = {
- "Big5",
- "EUC-JP",
- "EUC-KR",
- "gb18030",
- "GBK",
- "IBM866",
- "ISO-2022-JP",
- "ISO-8859-10",
- "ISO-8859-13",
- "ISO-8859-14",
- "ISO-8859-15",
- "ISO-8859-16",
- "ISO-8859-2",
- "ISO-8859-3",
- "ISO-8859-4",
- "ISO-8859-5",
- "ISO-8859-6",
- "ISO-8859-7",
- "ISO-8859-8",
- "ISO-8859-8-I",
- "KOI8-R",
- "KOI8-U",
- "macintosh",
- "Shift_JIS",
- "UTF-16LE",
- "UTF-8",
- "windows-1250",
- "windows-1251",
- "windows-1252",
- "windows-1253",
- "windows-1254",
- "windows-1255",
- "windows-1256",
- "windows-1257",
- "windows-1258",
- "windows-874"
+const CanonicalEncodingData kCanonicalEncodingNames[] = {
+ { IDC_ENCODING_UTF8, "UTF-8", IDS_ENCODING_UNICODE },
+ { IDC_ENCODING_UTF16LE, "UTF-16LE", IDS_ENCODING_UNICODE },
+ { IDC_ENCODING_WINDOWS1252, "windows-1252", IDS_ENCODING_WESTERN },
+ { IDC_ENCODING_GBK, "GBK", IDS_ENCODING_SIMP_CHINESE },
+ { IDC_ENCODING_GB18030, "gb18030", IDS_ENCODING_SIMP_CHINESE },
+ { IDC_ENCODING_BIG5, "Big5", IDS_ENCODING_TRAD_CHINESE },
+ { IDC_ENCODING_KOREAN, "EUC-KR", IDS_ENCODING_KOREAN },
+ { IDC_ENCODING_SHIFTJIS, "Shift_JIS", IDS_ENCODING_JAPANESE },
+ { IDC_ENCODING_EUCJP, "EUC-JP", IDS_ENCODING_JAPANESE },
+ { IDC_ENCODING_ISO2022JP, "ISO-2022-JP", IDS_ENCODING_JAPANESE },
+ { IDC_ENCODING_THAI, "windows-874", IDS_ENCODING_THAI },
+ { IDC_ENCODING_ISO885915, "ISO-8859-15", IDS_ENCODING_WESTERN },
+ { IDC_ENCODING_MACINTOSH, "macintosh", IDS_ENCODING_WESTERN },
+ { IDC_ENCODING_ISO88592, "ISO-8859-2", IDS_ENCODING_CENTRAL_EUROPEAN },
+ { IDC_ENCODING_WINDOWS1250, "windows-1250", IDS_ENCODING_CENTRAL_EUROPEAN },
+ { IDC_ENCODING_ISO88595, "ISO-8859-5", IDS_ENCODING_CYRILLIC },
+ { IDC_ENCODING_WINDOWS1251, "windows-1251", IDS_ENCODING_CYRILLIC },
+ { IDC_ENCODING_KOI8R, "KOI8-R", IDS_ENCODING_CYRILLIC },
+ { IDC_ENCODING_KOI8U, "KOI8-U", IDS_ENCODING_CYRILLIC },
+ { IDC_ENCODING_IBM866, "IBM866", IDS_ENCODING_CYRILLIC },
+ { IDC_ENCODING_ISO88597, "ISO-8859-7", IDS_ENCODING_GREEK },
+ { IDC_ENCODING_WINDOWS1253, "windows-1253", IDS_ENCODING_GREEK },
+ { IDC_ENCODING_WINDOWS1254, "windows-1254", IDS_ENCODING_TURKISH },
+ { IDC_ENCODING_WINDOWS1256, "windows-1256", IDS_ENCODING_ARABIC },
+ { IDC_ENCODING_ISO88596, "ISO-8859-6", IDS_ENCODING_ARABIC },
+ { IDC_ENCODING_WINDOWS1255, "windows-1255", IDS_ENCODING_HEBREW },
+ { IDC_ENCODING_ISO88598I, "ISO-8859-8-I", IDS_ENCODING_HEBREW },
+ { IDC_ENCODING_ISO88598, "ISO-8859-8", IDS_ENCODING_HEBREW },
+ { IDC_ENCODING_WINDOWS1258, "windows-1258", IDS_ENCODING_VIETNAMESE },
+ { IDC_ENCODING_ISO88594, "ISO-8859-4", IDS_ENCODING_BALTIC },
+ { IDC_ENCODING_ISO885913, "ISO-8859-13", IDS_ENCODING_BALTIC },
+ { IDC_ENCODING_WINDOWS1257, "windows-1257", IDS_ENCODING_BALTIC },
+ { IDC_ENCODING_ISO88593, "ISO-8859-3", IDS_ENCODING_SOUTH_EUROPEAN },
+ { IDC_ENCODING_ISO885910, "ISO-8859-10", IDS_ENCODING_NORDIC },
+ { IDC_ENCODING_ISO885914, "ISO-8859-14", IDS_ENCODING_CELTIC },
+ { IDC_ENCODING_ISO885916, "ISO-8859-16", IDS_ENCODING_ROMANIAN },
};
-} // namespace
-std::string GetCanonicalEncodingNameByAliasName(const std::string& alias_name) {
- for (size_t i = 0; i < arraysize(kCanonicalEncodingNames); ++i) {
- if (alias_name == kCanonicalEncodingNames[i])
- return alias_name;
+const int kCanonicalEncodingNamesLength = arraysize(kCanonicalEncodingNames);
+
+typedef std::map<int, std::pair<const char*, int> >
+ IdToCanonicalEncodingNameMapType;
+typedef std::map<const std::string, int> CanonicalEncodingNameToIdMapType;
+
+typedef struct {
+ const char* canonical_form;
+ const char* display_form;
+} CanonicalEncodingDisplayNamePair;
+
+const CanonicalEncodingDisplayNamePair kCanonicalDisplayNameOverrides[] = {
+ // Only lists the canonical names where we want a different form for display.
+ { "macintosh", "Macintosh" },
+ { "windows-874", "Windows-874" },
+ { "windows-1250", "Windows-1250" },
+ { "windows-1251", "Windows-1251" },
+ { "windows-1252", "Windows-1252" },
+ { "windows-1253", "Windows-1253" },
+ { "windows-1254", "Windows-1254" },
+ { "windows-1255", "Windows-1255" },
+ { "windows-1256", "Windows-1256" },
+ { "windows-1257", "Windows-1257" },
+ { "windows-1258", "Windows-1258" },
+};
+
+const int kCanonicalDisplayNameOverridesLength =
+ arraysize(kCanonicalDisplayNameOverrides);
+
+typedef std::map<std::string, const char*> CanonicalNameDisplayNameMapType;
+
+class CanonicalEncodingMap {
+ public:
+ CanonicalEncodingMap() {}
+ const IdToCanonicalEncodingNameMapType* GetIdToCanonicalEncodingNameMapData();
+ const CanonicalEncodingNameToIdMapType* GetCanonicalEncodingNameToIdMapData();
+ const CanonicalNameDisplayNameMapType* GetCanonicalNameDisplayNameMapData();
+ std::vector<int>* locale_dependent_encoding_ids() {
+ return &locale_dependent_encoding_ids_;
+ }
+
+ std::vector<CharacterEncoding::EncodingInfo>* current_display_encodings() {
+ return &current_display_encodings_;
+ }
+
+ private:
+ std::unique_ptr<IdToCanonicalEncodingNameMapType> id_to_encoding_name_map_;
+ std::unique_ptr<CanonicalEncodingNameToIdMapType> encoding_name_to_id_map_;
+ std::unique_ptr<CanonicalNameDisplayNameMapType>
+ encoding_name_to_display_name_map_;
+ std::vector<int> locale_dependent_encoding_ids_;
+ std::vector<CharacterEncoding::EncodingInfo> current_display_encodings_;
+
+ DISALLOW_COPY_AND_ASSIGN(CanonicalEncodingMap);
+};
+
+const IdToCanonicalEncodingNameMapType*
+ CanonicalEncodingMap::GetIdToCanonicalEncodingNameMapData() {
+ // Testing and building map is not thread safe, this function is supposed to
+ // only run in UI thread. Myabe I should add a lock in here for making it as
+ // thread safe.
+ if (!id_to_encoding_name_map_.get()) {
+ id_to_encoding_name_map_.reset(new IdToCanonicalEncodingNameMapType);
+ for (int i = 0; i < kCanonicalEncodingNamesLength; ++i) {
+ int resource_id = kCanonicalEncodingNames[i].resource_id;
+ (*id_to_encoding_name_map_)[resource_id] =
+ std::make_pair(kCanonicalEncodingNames[i].name,
+ kCanonicalEncodingNames[i].category_string_id);
+ }
}
+ return id_to_encoding_name_map_.get();
+}
+
+const CanonicalEncodingNameToIdMapType*
+ CanonicalEncodingMap::GetCanonicalEncodingNameToIdMapData() {
+ if (!encoding_name_to_id_map_.get()) {
+ encoding_name_to_id_map_.reset(new CanonicalEncodingNameToIdMapType);
+ for (int i = 0; i < kCanonicalEncodingNamesLength; ++i) {
+ (*encoding_name_to_id_map_)[kCanonicalEncodingNames[i].name] =
+ kCanonicalEncodingNames[i].resource_id;
+ }
+ }
+ return encoding_name_to_id_map_.get();
+}
+
+const CanonicalNameDisplayNameMapType*
+ CanonicalEncodingMap::GetCanonicalNameDisplayNameMapData() {
+ if (!encoding_name_to_display_name_map_.get()) {
+ encoding_name_to_display_name_map_.reset(
+ new CanonicalNameDisplayNameMapType);
+ // First store the names in the kCanonicalEncodingNames list.
+ for (int i = 0; i < kCanonicalEncodingNamesLength; ++i) {
+ (*encoding_name_to_display_name_map_)[kCanonicalEncodingNames[i].name] =
+ kCanonicalEncodingNames[i].name;
+ }
+ // Then save in the overrides.
+ for (int i = 0; i < kCanonicalDisplayNameOverridesLength; ++i) {
+ (*encoding_name_to_display_name_map_)
+ [kCanonicalDisplayNameOverrides[i].canonical_form] =
+ kCanonicalDisplayNameOverrides[i].display_form;
+ }
+ DCHECK(static_cast<int>(encoding_name_to_display_name_map_->size()) ==
+ kCanonicalEncodingNamesLength)
+ << "Got an override that wasn't in the encoding list";
+ }
+ return encoding_name_to_display_name_map_.get();
+}
+
+// A static map object which contains all resourceid-nonsequenced canonical
+// encoding names.
+CanonicalEncodingMap* CanonicalEncodingMapSingleton() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ static CanonicalEncodingMap* singleton = new CanonicalEncodingMap;
+ return singleton;
+}
+
+const int kDefaultEncodingMenus[] = {
+ IDC_ENCODING_UTF16LE,
+ IDC_ENCODING_WINDOWS1252,
+ IDC_ENCODING_GBK,
+ IDC_ENCODING_GB18030,
+ IDC_ENCODING_BIG5,
+ IDC_ENCODING_KOREAN,
+ IDC_ENCODING_SHIFTJIS,
+ IDC_ENCODING_EUCJP,
+ IDC_ENCODING_ISO2022JP,
+ IDC_ENCODING_THAI,
+ IDC_ENCODING_ISO885915,
+ IDC_ENCODING_MACINTOSH,
+ IDC_ENCODING_ISO88592,
+ IDC_ENCODING_WINDOWS1250,
+ IDC_ENCODING_ISO88595,
+ IDC_ENCODING_WINDOWS1251,
+ IDC_ENCODING_KOI8R,
+ IDC_ENCODING_KOI8U,
+ IDC_ENCODING_IBM866,
+ IDC_ENCODING_ISO88597,
+ IDC_ENCODING_WINDOWS1253,
+ IDC_ENCODING_WINDOWS1254,
+ IDC_ENCODING_WINDOWS1256,
+ IDC_ENCODING_ISO88596,
+ IDC_ENCODING_WINDOWS1255,
+ IDC_ENCODING_ISO88598I,
+ IDC_ENCODING_ISO88598,
+ IDC_ENCODING_WINDOWS1258,
+ IDC_ENCODING_ISO88594,
+ IDC_ENCODING_ISO885913,
+ IDC_ENCODING_WINDOWS1257,
+ IDC_ENCODING_ISO88593,
+ IDC_ENCODING_ISO885910,
+ IDC_ENCODING_ISO885914,
+ IDC_ENCODING_ISO885916,
+};
+
+const int kDefaultEncodingMenusLength = arraysize(kDefaultEncodingMenus);
+
+// Parse the input |encoding_list| which is a encoding list separated with
+// comma, get available encoding ids and save them to |available_list|.
+// The parameter |maximum_size| indicates maximum size of encoding items we
+// want to get from the |encoding_list|.
+void ParseEncodingListSeparatedWithComma(
+ const std::string& encoding_list, std::vector<int>* const available_list,
+ size_t maximum_size) {
+ base::StringTokenizer tokenizer(encoding_list, ",");
+ while (tokenizer.GetNext()) {
+ int id = CharacterEncoding::GetCommandIdByCanonicalEncodingName(
+ tokenizer.token());
+ // Ignore invalid encoding.
+ if (!id)
+ continue;
+ available_list->push_back(id);
+ if (available_list->size() == maximum_size)
+ return;
+ }
+}
+
+base::string16 GetEncodingDisplayName(const std::string& encoding_name,
+ int category_string_id) {
+ base::string16 category_name = l10n_util::GetStringUTF16(category_string_id);
+ if (category_string_id != IDS_ENCODING_KOREAN &&
+ category_string_id != IDS_ENCODING_THAI &&
+ category_string_id != IDS_ENCODING_TURKISH &&
+ category_string_id != IDS_ENCODING_VIETNAMESE &&
+ category_string_id != IDS_ENCODING_ROMANIAN) {
+ const CanonicalNameDisplayNameMapType* map =
+ CanonicalEncodingMapSingleton()->GetCanonicalNameDisplayNameMapData();
+ DCHECK(map);
+
+ CanonicalNameDisplayNameMapType::const_iterator found_name =
+ map->find(encoding_name);
+ DCHECK(found_name != map->end());
+ return l10n_util::GetStringFUTF16(IDS_ENCODING_DISPLAY_TEMPLATE,
+ category_name,
+ base::ASCIIToUTF16(found_name->second));
+ }
+ return category_name;
+}
+
+int GetEncodingCategoryStringIdByCommandId(int id) {
+ const IdToCanonicalEncodingNameMapType* map =
+ CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
+ DCHECK(map);
+
+ IdToCanonicalEncodingNameMapType::const_iterator found_name = map->find(id);
+ if (found_name != map->end())
+ return found_name->second.second;
+ return 0;
+}
+
+std::string GetEncodingCategoryStringByCommandId(int id) {
+ int category_id = GetEncodingCategoryStringIdByCommandId(id);
+ if (category_id)
+ return l10n_util::GetStringUTF8(category_id);
+ return std::string();
+}
+
+} // namespace
+
+CharacterEncoding::EncodingInfo::EncodingInfo(int id)
+ : encoding_id(id) {
+ encoding_category_name =
+ base::UTF8ToUTF16(GetEncodingCategoryStringByCommandId(id));
+ encoding_display_name = GetCanonicalEncodingDisplayNameByCommandId(id);
+}
+
+// Static.
+int CharacterEncoding::GetCommandIdByCanonicalEncodingName(
+ const std::string& encoding_name) {
+ const CanonicalEncodingNameToIdMapType* map =
+ CanonicalEncodingMapSingleton()->GetCanonicalEncodingNameToIdMapData();
+ DCHECK(map);
+
+ CanonicalEncodingNameToIdMapType::const_iterator found_id =
+ map->find(encoding_name);
+ if (found_id != map->end())
+ return found_id->second;
+ return 0;
+}
+
+// Static.
+std::string CharacterEncoding::GetCanonicalEncodingNameByCommandId(int id) {
+ const IdToCanonicalEncodingNameMapType* map =
+ CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
+ DCHECK(map);
+
+ IdToCanonicalEncodingNameMapType::const_iterator found_name = map->find(id);
+ if (found_name != map->end())
+ return found_name->second.first;
+ return std::string();
+}
+
+// Static.
+base::string16 CharacterEncoding::GetCanonicalEncodingDisplayNameByCommandId(
+ int id) {
+ const IdToCanonicalEncodingNameMapType* map =
+ CanonicalEncodingMapSingleton()->GetIdToCanonicalEncodingNameMapData();
+ DCHECK(map);
+
+ IdToCanonicalEncodingNameMapType::const_iterator found_name = map->find(id);
+ if (found_name != map->end())
+ return GetEncodingDisplayName(found_name->second.first,
+ found_name->second.second);
+ return base::string16();
+}
+
+// Static.
+// Return count number of all supported canonical encoding.
+int CharacterEncoding::GetSupportCanonicalEncodingCount() {
+ return kCanonicalEncodingNamesLength;
+}
+
+// Static.
+std::string CharacterEncoding::GetCanonicalEncodingNameByIndex(int index) {
+ if (index < kCanonicalEncodingNamesLength)
+ return kCanonicalEncodingNames[index].name;
+ return std::string();
+}
+
+// Static.
+base::string16 CharacterEncoding::GetCanonicalEncodingDisplayNameByIndex(
+ int index) {
+ if (index < kCanonicalEncodingNamesLength)
+ return GetEncodingDisplayName(kCanonicalEncodingNames[index].name,
+ kCanonicalEncodingNames[index].category_string_id);
+ return base::string16();
+}
+
+// Static.
+int CharacterEncoding::GetEncodingCommandIdByIndex(int index) {
+ if (index < kCanonicalEncodingNamesLength)
+ return kCanonicalEncodingNames[index].resource_id;
+ return 0;
+}
+
+// Static.
+std::string CharacterEncoding::GetCanonicalEncodingNameByAliasName(
+ const std::string& alias_name) {
+ // If the input alias_name is already canonical encoding name, just return it.
+ const CanonicalEncodingNameToIdMapType* map =
+ CanonicalEncodingMapSingleton()->GetCanonicalEncodingNameToIdMapData();
+ DCHECK(map);
+
+ CanonicalEncodingNameToIdMapType::const_iterator found_id =
+ map->find(alias_name);
+ if (found_id != map->end())
+ return alias_name;
+
const char* standards[3] = { "HTML", "MIME", "IANA" };
for (size_t i = 0; i < arraysize(standards); ++i) {
UErrorCode error_code = U_ZERO_ERROR;
@@ -65,3 +392,140 @@ std::string GetCanonicalEncodingNameByAliasName(const std::string& alias_name) {
}
return std::string();
}
+
+// Static
+// According to the behavior of user recently selected encoding short list in
+// Firefox, we always put UTF-8 as top position, after then put user
+// recent selected encodings, then put local dependent encoding items.
+// At last, we put all remaining encoding items.
+const std::vector<CharacterEncoding::EncodingInfo>*
+ CharacterEncoding::GetCurrentDisplayEncodings(
+ const std::string& locale,
+ const std::string& locale_encodings,
+ const std::string& recently_select_encodings) {
+ std::vector<int>* const locale_dependent_encoding_list =
+ CanonicalEncodingMapSingleton()->locale_dependent_encoding_ids();
+ std::vector<CharacterEncoding::EncodingInfo>* const encoding_list =
+ CanonicalEncodingMapSingleton()->current_display_encodings();
+
+ // Initialize locale dependent static encoding list.
+ if (locale_dependent_encoding_list->empty() && !locale_encodings.empty())
+ ParseEncodingListSeparatedWithComma(locale_encodings,
+ locale_dependent_encoding_list,
+ kUserSelectedEncodingsMaxLength);
+
+ CR_DEFINE_STATIC_LOCAL(std::string, cached_user_selected_encodings, ());
+ // Build current display encoding list.
+ if (encoding_list->empty() ||
+ cached_user_selected_encodings != recently_select_encodings) {
+ // Update user recently selected encodings.
+ cached_user_selected_encodings = recently_select_encodings;
+ // Clear old encoding list since user recently selected encodings changed.
+ encoding_list->clear();
+ // Always add UTF-8 to first encoding position.
+ encoding_list->push_back(EncodingInfo(IDC_ENCODING_UTF8));
+ std::set<int> inserted_encoding;
+ inserted_encoding.insert(IDC_ENCODING_UTF8);
+
+ // Parse user recently selected encodings and get list
+ std::vector<int> recently_select_encoding_list;
+ ParseEncodingListSeparatedWithComma(recently_select_encodings,
+ &recently_select_encoding_list,
+ kUserSelectedEncodingsMaxLength);
+
+ // Put 'cached encodings' (dynamic encoding list) after 'local dependent
+ // encoding list'.
+ recently_select_encoding_list.insert(recently_select_encoding_list.begin(),
+ locale_dependent_encoding_list->begin(),
+ locale_dependent_encoding_list->end());
+ for (std::vector<int>::iterator it = recently_select_encoding_list.begin();
+ it != recently_select_encoding_list.end(); ++it) {
+ // Test whether we have met this encoding id.
+ bool ok = inserted_encoding.insert(*it).second;
+ // Duplicated encoding, ignore it. Ideally, this situation should not
+ // happened, but just in case some one manually edit preference file.
+ if (!ok)
+ continue;
+ encoding_list->push_back(EncodingInfo(*it));
+ }
+ // Append a separator;
+ encoding_list->push_back(EncodingInfo(0));
+
+ // We need to keep "Unicode (UTF-16LE)" always at the top (among the rest
+ // of encodings) instead of being sorted along with other encodings. So if
+ // "Unicode (UTF-16LE)" is already in previous encodings, sort the rest
+ // of encodings. Otherwise Put "Unicode (UTF-16LE)" on the first of the
+ // rest of encodings, skip "Unicode (UTF-16LE)" and sort all left encodings.
+ int start_sorted_index = encoding_list->size();
+ if (inserted_encoding.find(IDC_ENCODING_UTF16LE) ==
+ inserted_encoding.end()) {
+ encoding_list->push_back(EncodingInfo(IDC_ENCODING_UTF16LE));
+ inserted_encoding.insert(IDC_ENCODING_UTF16LE);
+ start_sorted_index++;
+ }
+
+ // Add the rest of encodings that are neither in the static encoding list
+ // nor in the list of recently selected encodings.
+ // Build the encoding list sorted in the current locale sorting order.
+ for (int i = 0; i < kDefaultEncodingMenusLength; ++i) {
+ int id = kDefaultEncodingMenus[i];
+ // We have inserted this encoding, skip it.
+ if (inserted_encoding.find(id) != inserted_encoding.end())
+ continue;
+ encoding_list->push_back(EncodingInfo(id));
+ }
+ // Sort the encoding list.
+ l10n_util::SortVectorWithStringKey(locale,
+ encoding_list,
+ start_sorted_index,
+ encoding_list->size(),
+ true);
+ }
+ DCHECK(!encoding_list->empty());
+ return encoding_list;
+}
+
+// Static
+bool CharacterEncoding::UpdateRecentlySelectedEncoding(
+ const std::string& original_selected_encodings,
+ int new_selected_encoding_id,
+ std::string* selected_encodings) {
+ // Get encoding name.
+ std::string encoding_name =
+ GetCanonicalEncodingNameByCommandId(new_selected_encoding_id);
+ DCHECK(!encoding_name.empty());
+ // Check whether the new encoding is in local dependent encodings or original
+ // recently selected encodings. If yes, do not add it.
+ std::vector<int>* locale_dependent_encoding_list =
+ CanonicalEncodingMapSingleton()->locale_dependent_encoding_ids();
+ DCHECK(locale_dependent_encoding_list);
+ std::vector<int> selected_encoding_list;
+ ParseEncodingListSeparatedWithComma(original_selected_encodings,
+ &selected_encoding_list,
+ kUserSelectedEncodingsMaxLength);
+ // Put 'cached encodings' (dynamic encoding list) after 'local dependent
+ // encoding list' for check.
+ std::vector<int> top_encoding_list(*locale_dependent_encoding_list);
+ // UTF8 is always in our optimized encoding list.
+ top_encoding_list.insert(top_encoding_list.begin(), IDC_ENCODING_UTF8);
+ top_encoding_list.insert(top_encoding_list.end(),
+ selected_encoding_list.begin(),
+ selected_encoding_list.end());
+ for (std::vector<int>::const_iterator it = top_encoding_list.begin();
+ it != top_encoding_list.end(); ++it)
+ if (*it == new_selected_encoding_id)
+ return false;
+ // Need to add the encoding id to recently selected encoding list.
+ // Remove the last encoding in original list.
+ if (selected_encoding_list.size() == kUserSelectedEncodingsMaxLength)
+ selected_encoding_list.pop_back();
+ // Insert new encoding to head of selected encoding list.
+ *selected_encodings = encoding_name;
+ // Generate the string for rest selected encoding list.
+ for (std::vector<int>::const_iterator it = selected_encoding_list.begin();
+ it != selected_encoding_list.end(); ++it) {
+ selected_encodings->append(1, L',');
+ selected_encodings->append(GetCanonicalEncodingNameByCommandId(*it));
+ }
+ return true;
+}
diff --git a/chrome/browser/character_encoding.h b/chrome/browser/character_encoding.h
index 52b210e3..2c70a17 100644
--- a/chrome/browser/character_encoding.h
+++ b/chrome/browser/character_encoding.h
@@ -6,9 +6,101 @@
#define CHROME_BROWSER_CHARACTER_ENCODING_H_
#include <string>
+#include <vector>
-// Return canonical encoding name according to the encoding alias name.
-// TODO(jinsukkim): Move this to somewhere under content/.
-std::string GetCanonicalEncodingNameByAliasName(const std::string& alias_name);
+#include "base/macros.h"
+#include "base/strings/string16.h"
+
+class CharacterEncoding {
+ public:
+ // Enumeration of the types of Browser encoding name we
+ // currently support. This is defined outside of Browser
+ // to avoid cyclical dependencies.
+
+ // Structure to save encoding information.
+ struct EncodingInfo {
+ explicit EncodingInfo(int id);
+ // Gets string key of EncodingInfo. With this method, we can use
+ // l10n_util::SortVectorWithStringKey to sort the encoding menu items
+ // by current locale character sequence. We need to keep the order within
+ // encoding category name, that's why we use category name as key.
+ const base::string16& GetStringKey() const { return encoding_category_name; }
+
+ // Encoding command id.
+ int encoding_id;
+ // Encoding display name.
+ base::string16 encoding_display_name;
+ // Encoding category name.
+ base::string16 encoding_category_name;
+ };
+
+ // Return canonical encoding name according to the command ID.
+ // THIS FUNCTION IS NOT THREADSAFE. You must run this function
+ // only in UI thread.
+ static std::string GetCanonicalEncodingNameByCommandId(int id);
+
+ // Return display name of canonical encoding according to the command
+ // ID. THIS FUNCTION IS NOT THREADSAFE. You must run this function
+ // only in UI thread.
+ static base::string16 GetCanonicalEncodingDisplayNameByCommandId(int id);
+
+ // Return count number of all supported canonical encoding.
+ static int GetSupportCanonicalEncodingCount();
+
+ // Return canonical encoding name according to the index, which starts
+ // from zero to GetSupportCanonicalEncodingCount() - 1. THIS FUNCTION
+ // IS NOT THREADSAFE. You must run this function only in UI thread.
+ static std::string GetCanonicalEncodingNameByIndex(int index);
+
+ // Return display name of canonical encoding according to the index,
+ // which starts from zero to GetSupportCanonicalEncodingCount() - 1.
+ // THIS FUNCTION IS NOT THREADSAFE. You must run this function
+ // only in UI thread.
+ static base::string16 GetCanonicalEncodingDisplayNameByIndex(int index);
+
+ // Return encoding command id according to the index, which starts from
+ // zero to GetSupportCanonicalEncodingCount() - 1. Otherwise returns 0.
+ static int GetEncodingCommandIdByIndex(int index);
+
+ // Return canonical encoding name according to the encoding alias name. THIS
+ // FUNCTION IS NOT THREADSAFE. You must run this function only in UI thread.
+ static std::string GetCanonicalEncodingNameByAliasName(
+ const std::string& alias_name);
+
+ // Returns the pointer of a vector of EncodingInfos corresponding to
+ // encodings to display in the encoding menu. The locale-dependent static
+ // encodings come at the top of the list and recently selected encodings
+ // come next. Finally, the rest of encodings are listed.
+ // The vector will be created and destroyed by CharacterEncoding.
+ // The returned std::vector is maintained by this class. The parameter
+ // |locale| points to the current application (UI) locale. The parameter
+ // |locale_encodings| is string of static encodings list which is from the
+ // corresponding string resource that is stored in the resource bundle.
+ // The parameter |recently_select_encodings| is string of encoding list which
+ // is from user recently selected. THIS FUNCTION IS NOT THREADSAFE. You must
+ // run this function only in UI thread.
+ static const std::vector<EncodingInfo>* GetCurrentDisplayEncodings(
+ const std::string& locale,
+ const std::string& locale_encodings,
+ const std::string& recently_select_encodings);
+
+ // This function is for updating |original_selected_encoding_list| with a
+ // |new_selected_encoding_id|. If the encoding is already in the original
+ // list, then returns false. Otherwise |selected_encoding_list| will return a
+ // new string for user selected encoding short list and function returns true.
+ static bool UpdateRecentlySelectedEncoding(
+ const std::string& original_selected_encodings,
+ int new_selected_encoding_id,
+ std::string* selected_encodings);
+
+ // Get encoding command id according to input encoding name. If the name is
+ // valid, return corresponding encoding command id. Otherwise return 0;
+ static int GetCommandIdByCanonicalEncodingName(
+ const std::string& encoding_name);
+
+ private:
+ // Disallow instantiating it since this class only contains static methods.
+ DISALLOW_IMPLICIT_CONSTRUCTORS(CharacterEncoding);
+};
#endif // CHROME_BROWSER_CHARACTER_ENCODING_H_
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index f3e709a..ad35d8f 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1365,7 +1365,7 @@ bool ChromeContentBrowserClient::ShouldAssignSiteForURL(const GURL& url) {
std::string ChromeContentBrowserClient::GetCanonicalEncodingNameByAliasName(
const std::string& alias_name) {
- return ::GetCanonicalEncodingNameByAliasName(alias_name);
+ return CharacterEncoding::GetCanonicalEncodingNameByAliasName(alias_name);
}
namespace {
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 88bd093..f0c8f0f 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -308,6 +308,7 @@ const char kDesktopSearchRedirectionInfobarShownPref[] =
const char kNetworkPredictionEnabled[] = "dns_prefetching.enabled";
const char kDisableSpdy[] = "spdy.disabled";
+#if 0
// Deprecated 8/2016.
const char kRecentlySelectedEncoding[] = "profile.recently_selected_encodings";
const char kStaticEncodings[] = "intl.static_encodings";
@@ -315,6 +320,7 @@ const char kStaticEncodings[] = "intl.static_encodings";
// Deprecated 9/2016.
const char kWebKitUsesUniversalDetector[] =
"webkit.webprefs.uses_universal_detector";
+#endif // 0
const char kWebKitAllowDisplayingInsecureContent[] =
"webkit.webprefs.allow_displaying_insecure_content";
@@ -666,9 +675,11 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(kNetworkPredictionEnabled, true);
registry->RegisterBooleanPref(kDisableSpdy, false);
+#if 0
registry->RegisterStringPref(kStaticEncodings, std::string());
registry->RegisterStringPref(kRecentlySelectedEncoding, std::string());
registry->RegisterBooleanPref(kWebKitUsesUniversalDetector, true);
+#endif // 0
registry->RegisterBooleanPref(kWebKitAllowDisplayingInsecureContent, true);
}
@@ -770,12 +788,14 @@ void MigrateObsoleteProfilePrefs(Profile* profile) {
profile_prefs->ClearPref(kNetworkPredictionEnabled);
profile_prefs->ClearPref(kDisableSpdy);
+#if 0
// Added 8/2016.
profile_prefs->ClearPref(kStaticEncodings);
profile_prefs->ClearPref(kRecentlySelectedEncoding);
// Added 9/2016.
profile_prefs->ClearPref(kWebKitUsesUniversalDetector);
+#endif // 0
profile_prefs->ClearPref(kWebKitAllowDisplayingInsecureContent);
}
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 7bd0957..18653b5 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -850,6 +850,8 @@ split_static_library("ui") {
"toolbar/bookmark_sub_menu_model.h",
"toolbar/component_toolbar_actions_factory.cc",
"toolbar/component_toolbar_actions_factory.h",
+ "toolbar/encoding_menu_controller.cc",
+ "toolbar/encoding_menu_controller.h",
"toolbar/recent_tabs_sub_menu_model.cc",
"toolbar/recent_tabs_sub_menu_model.h",
"toolbar/toolbar_action_view_controller.h",
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 869fbec..0a7bddc 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -38,6 +38,7 @@
#include "chrome/browser/banners/app_banner_manager_desktop.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
+#include "chrome/browser/character_encoding.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
@@ -413,6 +421,11 @@ Browser::Browser(const CreateParams& params)
base::Bind(&Browser::UpdateBookmarkBarState, base::Unretained(this),
BOOKMARK_BAR_STATE_CHANGE_PREF_CHANGE));
+ // NOTE: These prefs all need to be explicitly destroyed in the destructor
+ // or you'll get a nasty surprise when you run the incognito tests.
+ encoding_auto_detect_.Init(prefs::kWebKitUsesUniversalDetector,
+ profile_->GetPrefs());
+
if (search::IsInstantExtendedAPIEnabled() && is_type_tabbed())
instant_controller_.reset(new BrowserInstantController(this));
@@ -489,6 +509,8 @@ Browser::~Browser() {
profile_pref_registrar_.RemoveAll();
+ encoding_auto_detect_.Destroy();
+
// Destroy BrowserExtensionWindowController before the incognito profile
// is destroyed to make sure the chrome.windows.onRemoved event is sent.
extension_window_controller_.reset();
@@ -819,6 +848,38 @@ bool Browser::CanSupportWindowFeature(WindowFeature feature) const {
return SupportsWindowFeatureImpl(feature, false);
}
+void Browser::ToggleEncodingAutoDetect() {
+ content::RecordAction(UserMetricsAction("AutoDetectChange"));
+ encoding_auto_detect_.SetValue(!encoding_auto_detect_.GetValue());
+ // If "auto detect" is turned on, then any current override encoding
+ // is cleared. This also implicitly performs a reload.
+ // OTOH, if "auto detect" is turned off, we don't change the currently
+ // active encoding.
+ if (encoding_auto_detect_.GetValue()) {
+ WebContents* contents = tab_strip_model_->GetActiveWebContents();
+ if (contents)
+ contents->ResetOverrideEncoding();
+ }
+}
+
+void Browser::OverrideEncoding(int encoding_id) {
+ content::RecordAction(UserMetricsAction("OverrideEncoding"));
+ const std::string selected_encoding =
+ CharacterEncoding::GetCanonicalEncodingNameByCommandId(encoding_id);
+ WebContents* contents = tab_strip_model_->GetActiveWebContents();
+ if (!selected_encoding.empty() && contents)
+ contents->SetOverrideEncoding(selected_encoding);
+ // Update the list of recently selected encodings.
+ std::string new_selected_encoding_list;
+ if (CharacterEncoding::UpdateRecentlySelectedEncoding(
+ profile_->GetPrefs()->GetString(prefs::kRecentlySelectedEncoding),
+ encoding_id,
+ &new_selected_encoding_list)) {
+ profile_->GetPrefs()->SetString(prefs::kRecentlySelectedEncoding,
+ new_selected_encoding_list);
+ }
+}
+
void Browser::OpenFile() {
content::RecordAction(UserMetricsAction("OpenFile"));
select_file_dialog_ = ui::SelectFileDialog::Create(
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 5410f5a..44c65ce 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -387,6 +387,11 @@ class Browser : public TabStripModelObserver,
// in |SupportsWindowFeature| for details on this.
bool CanSupportWindowFeature(WindowFeature feature) const;
+ // TODO(port): port these, and re-merge the two function declaration lists.
+ // Page-related commands.
+ void ToggleEncodingAutoDetect();
+ void OverrideEncoding(int encoding_id);
+
// Show various bits of UI
void OpenFile();
@@ -966,6 +978,9 @@ class Browser : public TabStripModelObserver,
// Dialog box used for opening and saving files.
scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
+ // Keep track of the encoding auto detect pref.
+ BooleanPrefMember encoding_auto_detect_;
+
// Helper which implements the ContentSettingBubbleModel interface.
std::unique_ptr<BrowserContentSettingBubbleModelDelegate>
content_setting_bubble_model_delegate_;
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index 7cbbbdd..fc325ef 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -98,6 +98,24 @@ enum WindowState {
WINDOW_STATE_FULLSCREEN,
};
+// Returns |true| if entry has an internal chrome:// URL, |false| otherwise.
+bool HasInternalURL(const NavigationEntry* entry) {
+ if (!entry)
+ return false;
+
+ // Check the |virtual_url()| first. This catches regular chrome:// URLs
+ // including URLs that were rewritten (such as chrome://bookmarks).
+ if (entry->GetVirtualURL().SchemeIs(content::kChromeUIScheme))
+ return true;
+
+ // If the |virtual_url()| isn't a chrome:// URL, check if it's actually
+ // view-source: of a chrome:// URL.
+ if (entry->GetVirtualURL().SchemeIs(content::kViewSourceScheme))
+ return entry->GetURL().SchemeIs(content::kChromeUIScheme);
+
+ return false;
+}
+
} // namespace
namespace chrome {
@@ -460,6 +485,49 @@ void BrowserCommandController::ExecuteCommandWithDisposition(
ManagePasswordsForPage(browser_);
break;
+ // Page encoding commands
+ case IDC_ENCODING_AUTO_DETECT:
+ browser_->ToggleEncodingAutoDetect();
+ break;
+ case IDC_ENCODING_UTF8:
+ case IDC_ENCODING_UTF16LE:
+ case IDC_ENCODING_WINDOWS1252:
+ case IDC_ENCODING_GBK:
+ case IDC_ENCODING_GB18030:
+ case IDC_ENCODING_BIG5:
+ case IDC_ENCODING_KOREAN:
+ case IDC_ENCODING_SHIFTJIS:
+ case IDC_ENCODING_ISO2022JP:
+ case IDC_ENCODING_EUCJP:
+ case IDC_ENCODING_THAI:
+ case IDC_ENCODING_ISO885915:
+ case IDC_ENCODING_MACINTOSH:
+ case IDC_ENCODING_ISO88592:
+ case IDC_ENCODING_WINDOWS1250:
+ case IDC_ENCODING_ISO88595:
+ case IDC_ENCODING_WINDOWS1251:
+ case IDC_ENCODING_KOI8R:
+ case IDC_ENCODING_KOI8U:
+ case IDC_ENCODING_IBM866:
+ case IDC_ENCODING_ISO88597:
+ case IDC_ENCODING_WINDOWS1253:
+ case IDC_ENCODING_ISO88594:
+ case IDC_ENCODING_ISO885913:
+ case IDC_ENCODING_WINDOWS1257:
+ case IDC_ENCODING_ISO88593:
+ case IDC_ENCODING_ISO885910:
+ case IDC_ENCODING_ISO885914:
+ case IDC_ENCODING_ISO885916:
+ case IDC_ENCODING_WINDOWS1254:
+ case IDC_ENCODING_ISO88596:
+ case IDC_ENCODING_WINDOWS1256:
+ case IDC_ENCODING_ISO88598:
+ case IDC_ENCODING_ISO88598I:
+ case IDC_ENCODING_WINDOWS1255:
+ case IDC_ENCODING_WINDOWS1258:
+ browser_->OverrideEncoding(id);
+ break;
+
// Clipboard commands
case IDC_CUT:
case IDC_COPY:
@@ -772,6 +847,43 @@ void BrowserCommandController::InitCommandState() {
// Page-related commands
command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION, true);
command_updater_.UpdateCommandEnabled(IDC_MANAGE_PASSWORDS_FOR_PAGE, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_AUTO_DETECT, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF8, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF16LE, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1252, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_GBK, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_GB18030, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_THAI, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOREAN, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_SHIFTJIS, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO2022JP, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_EUCJP, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885915, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_MACINTOSH, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88592, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1250, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88595, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1251, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8R, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8U, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_IBM866, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88597, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1253, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88594, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885913, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1257, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88593, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885910, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885914, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885916, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1254, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88596, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1256, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598I, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1255, true);
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1258, true);
// Zoom
command_updater_.UpdateCommandEnabled(IDC_ZOOM_MENU, true);
@@ -930,6 +1049,13 @@ void BrowserCommandController::UpdateCommandsForTabState() {
if (browser_->is_devtools())
command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, false);
+ // Changing the encoding is not possible on Chrome-internal webpages.
+ NavigationController& nc = current_web_contents->GetController();
+ bool is_chrome_internal = HasInternalURL(nc.GetLastCommittedEntry()) ||
+ current_web_contents->ShowingInterstitialPage();
+ command_updater_.UpdateCommandEnabled(IDC_ENCODING_MENU,
+ !is_chrome_internal && current_web_contents->IsSavable());
+
// Show various bits of UI
// TODO(pinkerton): Disable app-mode in the model until we implement it
// on the Mac. Be sure to remove both ifdefs. http://crbug.com/13148
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc
index 448bb72..604254a 100644
--- a/chrome/browser/ui/prefs/prefs_tab_helper.cc
+++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc
@@ -90,6 +90,7 @@ const char* const kPrefsToObserve[] = {
prefs::kWebKitPluginsEnabled,
prefs::kWebkitTabsToLinks,
prefs::kWebKitTextAreasAreResizable,
+ prefs::kWebKitUsesUniversalDetector,
prefs::kWebKitWebSecurityEnabled,
};
@@ -595,6 +603,14 @@ void PrefsTabHelper::RegisterProfilePrefs(
IDS_MINIMUM_FONT_SIZE);
RegisterLocalizedFontPref(registry, prefs::kWebKitMinimumLogicalFontSize,
IDS_MINIMUM_LOGICAL_FONT_SIZE);
+ registry->RegisterBooleanPref(
+ prefs::kWebKitUsesUniversalDetector,
+ l10n_util::GetStringUTF8(IDS_USES_UNIVERSAL_DETECTOR) == "true",
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+ registry->RegisterStringPref(
+ prefs::kStaticEncodings,
+ l10n_util::GetStringUTF8(IDS_STATIC_ENCODING_LIST));
+ registry->RegisterStringPref(prefs::kRecentlySelectedEncoding, std::string());
}
// static
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index f5b3b65..3368542 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -37,6 +37,7 @@
#include "chrome/browser/ui/global_error/global_error_service_factory.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/toolbar/bookmark_sub_menu_model.h"
+#include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
#include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
#include "chrome/browser/upgrade_detector.h"
@@ -108,6 +116,70 @@ base::string16 GetUpgradeDialogMenuItemName() {
} // namespace
+////////////////////////////////////////////////////////////////////////////////
+// EncodingMenuModel
+
+EncodingMenuModel::EncodingMenuModel(Browser* browser)
+ : ui::SimpleMenuModel(this),
+ browser_(browser) {
+ Build();
+}
+
+EncodingMenuModel::~EncodingMenuModel() {
+}
+
+void EncodingMenuModel::Build() {
+ EncodingMenuController::EncodingMenuItemList encoding_menu_items;
+ EncodingMenuController encoding_menu_controller;
+ encoding_menu_controller.GetEncodingMenuItems(browser_->profile(),
+ &encoding_menu_items);
+
+ int group_id = 0;
+ EncodingMenuController::EncodingMenuItemList::iterator it =
+ encoding_menu_items.begin();
+ for (; it != encoding_menu_items.end(); ++it) {
+ int id = it->first;
+ base::string16& label = it->second;
+ if (id == 0) {
+ AddSeparator(ui::NORMAL_SEPARATOR);
+ } else {
+ if (id == IDC_ENCODING_AUTO_DETECT) {
+ AddCheckItem(id, label);
+ } else {
+ // Use the id of the first radio command as the id of the group.
+ if (group_id <= 0)
+ group_id = id;
+ AddRadioItem(id, label, group_id);
+ }
+ }
+ }
+}
+
+bool EncodingMenuModel::IsCommandIdChecked(int command_id) const {
+ WebContents* current_tab =
+ browser_->tab_strip_model()->GetActiveWebContents();
+ if (!current_tab)
+ return false;
+ EncodingMenuController controller;
+ return controller.IsItemChecked(browser_->profile(),
+ current_tab->GetEncoding(), command_id);
+}
+
+bool EncodingMenuModel::IsCommandIdEnabled(int command_id) const {
+ bool enabled = chrome::IsCommandEnabled(browser_, command_id);
+ // Special handling for the contents of the Encoding submenu. On Mac OS,
+ // instead of enabling/disabling the top-level menu item, the submenu's
+ // contents get disabled, per Apple's HIG.
+#if defined(OS_MACOSX)
+ enabled &= chrome::IsCommandEnabled(browser_, IDC_ENCODING_MENU);
+#endif
+ return enabled;
+}
+
+void EncodingMenuModel::ExecuteCommand(int command_id, int event_flags) {
+ chrome::ExecuteCommand(browser_, command_id);
+}
+
////////////////////////////////////////////////////////////////////////////////
// ZoomMenuModel
@@ -203,6 +282,9 @@ void ToolsMenuModel::Build(Browser* browser) {
#if defined(OS_CHROMEOS)
AddItemWithStringId(IDC_TAKE_SCREENSHOT, IDS_TAKE_SCREENSHOT);
#endif
+ encoding_menu_model_.reset(new EncodingMenuModel(browser));
+ AddSubMenuWithStringId(IDC_ENCODING_MENU, IDS_ENCODING_MENU,
+ encoding_menu_model_.get());
AddSeparator(ui::NORMAL_SEPARATOR);
AddItemWithStringId(IDC_DEV_TOOLS, IDS_DEV_TOOLS);
diff --git a/chrome/browser/ui/toolbar/app_menu_model.h b/chrome/browser/ui/toolbar/app_menu_model.h
index 8900a00..bc086d6 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.h
+++ b/chrome/browser/ui/toolbar/app_menu_model.h
@@ -75,6 +75,26 @@ enum AppMenuAction {
LIMIT_MENU_ACTION
};
+// A menu model that builds the contents of an encoding menu.
+class EncodingMenuModel : public ui::SimpleMenuModel,
+ public ui::SimpleMenuModel::Delegate {
+ public:
+ explicit EncodingMenuModel(Browser* browser);
+ ~EncodingMenuModel() override;
+
+ // Overridden from ui::SimpleMenuModel::Delegate:
+ bool IsCommandIdChecked(int command_id) const override;
+ bool IsCommandIdEnabled(int command_id) const override;
+ void ExecuteCommand(int command_id, int event_flags) override;
+
+ private:
+ void Build();
+
+ Browser* browser_; // weak
+
+ DISALLOW_COPY_AND_ASSIGN(EncodingMenuModel);
+};
+
// A menu model that builds the contents of the zoom menu.
class ZoomMenuModel : public ui::SimpleMenuModel {
public:
@@ -95,6 +122,8 @@ class ToolsMenuModel : public ui::SimpleMenuModel {
private:
void Build(Browser* browser);
+ std::unique_ptr<EncodingMenuModel> encoding_menu_model_;
+
DISALLOW_COPY_AND_ASSIGN(ToolsMenuModel);
};
diff --git a/chrome/browser/ui/toolbar/encoding_menu_controller.cc b/chrome/browser/ui/toolbar/encoding_menu_controller.cc
new file mode 100644
index 0000000..08476d1
--- /dev/null
+++ b/chrome/browser/ui/toolbar/encoding_menu_controller.cc
@@ -0,0 +1,142 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
+
+#include <stddef.h>
+
+#include "base/i18n/rtl.h"
+#include "base/macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/character_encoding.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/prefs/pref_service.h"
+#include "ui/base/l10n/l10n_util.h"
+
+const int EncodingMenuController::kValidEncodingIds[] = {
+ IDC_ENCODING_UTF8,
+ IDC_ENCODING_UTF16LE,
+ IDC_ENCODING_WINDOWS1252,
+ IDC_ENCODING_GBK,
+ IDC_ENCODING_GB18030,
+ IDC_ENCODING_BIG5,
+ IDC_ENCODING_KOREAN,
+ IDC_ENCODING_SHIFTJIS,
+ IDC_ENCODING_ISO2022JP,
+ IDC_ENCODING_EUCJP,
+ IDC_ENCODING_THAI,
+ IDC_ENCODING_ISO885915,
+ IDC_ENCODING_MACINTOSH,
+ IDC_ENCODING_ISO88592,
+ IDC_ENCODING_WINDOWS1250,
+ IDC_ENCODING_ISO88595,
+ IDC_ENCODING_WINDOWS1251,
+ IDC_ENCODING_KOI8R,
+ IDC_ENCODING_KOI8U,
+ IDC_ENCODING_ISO88597,
+ IDC_ENCODING_WINDOWS1253,
+ IDC_ENCODING_ISO88594,
+ IDC_ENCODING_ISO885913,
+ IDC_ENCODING_WINDOWS1257,
+ IDC_ENCODING_ISO88593,
+ IDC_ENCODING_ISO885910,
+ IDC_ENCODING_ISO885914,
+ IDC_ENCODING_ISO885916,
+ IDC_ENCODING_WINDOWS1254,
+ IDC_ENCODING_ISO88596,
+ IDC_ENCODING_WINDOWS1256,
+ IDC_ENCODING_ISO88598,
+ IDC_ENCODING_WINDOWS1255,
+ IDC_ENCODING_WINDOWS1258,
+ IDC_ENCODING_ISO88598I,
+ IDC_ENCODING_IBM866,
+};
+
+bool EncodingMenuController::DoesCommandBelongToEncodingMenu(int id) {
+ if (id == IDC_ENCODING_AUTO_DETECT) {
+ return true;
+ }
+
+ for (size_t i = 0; i < arraysize(kValidEncodingIds); ++i) {
+ if (id == kValidEncodingIds[i]) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+const int* EncodingMenuController::ValidGUIEncodingIDs() {
+ return kValidEncodingIds;
+}
+
+int EncodingMenuController::NumValidGUIEncodingIDs() {
+ return arraysize(kValidEncodingIds);
+}
+
+bool EncodingMenuController::IsItemChecked(
+ Profile* browser_profile,
+ const std::string& current_tab_encoding,
+ int item_id) {
+ if (!DoesCommandBelongToEncodingMenu(item_id))
+ return false;
+
+ std::string encoding = current_tab_encoding;
+ if (encoding.empty())
+ encoding = browser_profile->GetPrefs()->GetString(prefs::kDefaultCharset);
+
+ if (item_id == IDC_ENCODING_AUTO_DETECT) {
+ return browser_profile->GetPrefs()->GetBoolean(
+ prefs::kWebKitUsesUniversalDetector);
+ }
+
+ if (!encoding.empty()) {
+ return encoding ==
+ CharacterEncoding::GetCanonicalEncodingNameByCommandId(item_id);
+ }
+
+ return false;
+}
+
+void EncodingMenuController::GetEncodingMenuItems(Profile* profile,
+ EncodingMenuItemList* menu_items) {
+
+ DCHECK(menu_items);
+ EncodingMenuItem separator(0, base::string16());
+
+ menu_items->clear();
+ menu_items->push_back(
+ EncodingMenuItem(IDC_ENCODING_AUTO_DETECT,
+ l10n_util::GetStringUTF16(IDS_ENCODING_AUTO_DETECT)));
+ menu_items->push_back(separator);
+
+ // Create current display encoding list.
+ const std::vector<CharacterEncoding::EncodingInfo>* encodings;
+
+ // Build the list of encoding ids : It is made of the
+ // locale-dependent short list, the cache of recently selected
+ // encodings and other encodings.
+ encodings = CharacterEncoding::GetCurrentDisplayEncodings(
+ g_browser_process->GetApplicationLocale(),
+ profile->GetPrefs()->GetString(prefs::kStaticEncodings),
+ profile->GetPrefs()->GetString(prefs::kRecentlySelectedEncoding));
+ DCHECK(encodings);
+ DCHECK(!encodings->empty());
+
+ // Build up output list for menu.
+ std::vector<CharacterEncoding::EncodingInfo>::const_iterator it;
+ for (it = encodings->begin(); it != encodings->end(); ++it) {
+ if (it->encoding_id) {
+ base::string16 encoding = it->encoding_display_name;
+ base::i18n::AdjustStringForLocaleDirection(&encoding);
+ menu_items->push_back(EncodingMenuItem(it->encoding_id, encoding));
+ } else {
+ menu_items->push_back(separator);
+ }
+ }
+}
diff --git a/chrome/browser/ui/toolbar/encoding_menu_controller.h b/chrome/browser/ui/toolbar/encoding_menu_controller.h
new file mode 100644
index 0000000..96d62fa
--- /dev/null
+++ b/chrome/browser/ui/toolbar/encoding_menu_controller.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_TOOLBAR_ENCODING_MENU_CONTROLLER_H_
+#define CHROME_BROWSER_UI_TOOLBAR_ENCODING_MENU_CONTROLLER_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+
+class Profile;
+
+// Cross-platform logic needed for the encoding menu.
+// For now, we don't need to track state so all methods are static.
+class EncodingMenuController {
+ FRIEND_TEST_ALL_PREFIXES(EncodingMenuControllerTest, EncodingIDsBelongTest);
+ FRIEND_TEST_ALL_PREFIXES(EncodingMenuControllerTest, IsItemChecked);
+
+ public:
+ typedef std::pair<int, base::string16> EncodingMenuItem;
+ typedef std::vector<EncodingMenuItem> EncodingMenuItemList;
+
+ public:
+ EncodingMenuController() {}
+
+ // Given a command ID, does this command belong to the encoding menu?
+ bool DoesCommandBelongToEncodingMenu(int id);
+
+ // Returns true if the given encoding menu item (specified by item_id)
+ // is checked. Note that this header is included from objc, where the name
+ // "id" is reserved.
+ bool IsItemChecked(Profile* browser_profile,
+ const std::string& current_tab_encoding,
+ int item_id);
+
+ // Fills in a list of menu items in the order they should appear in the menu.
+ // Items whose ids are 0 are separators.
+ void GetEncodingMenuItems(Profile* profile,
+ EncodingMenuItemList* menu_items);
+
+ private:
+ // List of all valid encoding GUI IDs.
+ static const int kValidEncodingIds[];
+ const int* ValidGUIEncodingIDs();
+ int NumValidGUIEncodingIDs();
+
+ DISALLOW_COPY_AND_ASSIGN(EncodingMenuController);
+};
+
+#endif // CHROME_BROWSER_UI_TOOLBAR_ENCODING_MENU_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/frame/system_menu_model_builder.cc b/chrome/browser/ui/views/frame/system_menu_model_builder.cc
index b2947db..f38a1eb 100644
--- a/chrome/browser/ui/views/frame/system_menu_model_builder.cc
+++ b/chrome/browser/ui/views/frame/system_menu_model_builder.cc
@@ -115,6 +115,10 @@ void SystemMenuModelBuilder::BuildSystemMenuForAppOrPopupWindow(
zoom_menu_contents_.reset(new ZoomMenuModel(&menu_delegate_));
model->AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_ZOOM_MENU,
zoom_menu_contents_.get());
+ encoding_menu_contents_.reset(new EncodingMenuModel(browser()));
+ model->AddSubMenuWithStringId(IDC_ENCODING_MENU,
+ IDS_ENCODING_MENU,
+ encoding_menu_contents_.get());
if (browser()->is_app() && chrome::CanOpenTaskManager()) {
model->AddSeparator(ui::NORMAL_SEPARATOR);
model->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
diff --git a/chrome/browser/ui/views/frame/system_menu_model_builder.h b/chrome/browser/ui/views/frame/system_menu_model_builder.h
index 51ed98f..50d9246 100644
--- a/chrome/browser/ui/views/frame/system_menu_model_builder.h
+++ b/chrome/browser/ui/views/frame/system_menu_model_builder.h
@@ -11,6 +11,7 @@
#include "chrome/browser/ui/views/frame/system_menu_model_delegate.h"
class Browser;
+class EncodingMenuModel;
class ZoomMenuModel;
namespace ui {
@@ -49,6 +57,7 @@ class SystemMenuModelBuilder {
SystemMenuModelDelegate menu_delegate_;
std::unique_ptr<ui::MenuModel> menu_model_;
std::unique_ptr<ZoomMenuModel> zoom_menu_contents_;
+ std::unique_ptr<EncodingMenuModel> encoding_menu_contents_;
DISALLOW_COPY_AND_ASSIGN(SystemMenuModelBuilder);
};
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 9eb3df7..5b2fd77 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -216,6 +216,11 @@ const char kDefaultCharset[] = "intl.charset_default";
// request.
const char kAcceptLanguages[] = "intl.accept_languages";
+// The value to use for showing locale-dependent encoding list for different
+// locale, it's initialized from the corresponding string resource that is
+// stored in non-translatable part of the resource bundle.
+const char kStaticEncodings[] = "intl.static_encodings";
+
// If these change, the corresponding enums in the extension API
// experimental.fontSettings.json must also change.
const char* const kWebKitScriptsForFontFamilyMaps[] = {
@@ -313,6 +325,8 @@ const char kWebKitSansSerifFontFamilyTraditionalHan[] =
// WebKit preferences.
const char kWebKitWebSecurityEnabled[] = "webkit.webprefs.web_security_enabled";
const char kWebKitDomPasteEnabled[] = "webkit.webprefs.dom_paste_enabled";
+const char kWebKitUsesUniversalDetector[] =
+ "webkit.webprefs.uses_universal_detector";
const char kWebKitTextAreasAreResizable[] =
"webkit.webprefs.text_areas_are_resizable";
const char kWebkitTabsToLinks[] = "webkit.webprefs.tabs_to_links";
@@ -906,6 +927,9 @@ const char kEolNotificationDismissed[] = "eol_notification_dismissed";
// visible on the toolbar.
const char kShowHomeButton[] = "browser.show_home_button";
+// A string value which saves short list of recently user selected encodings
+// separated with comma punctuation mark.
+const char kRecentlySelectedEncoding[] = "profile.recently_selected_encodings";
// Boolean pref to define the default setting for "block offensive words".
// The old key value is kept to avoid unnecessary migration code.
const char kSpeechRecognitionFilterProfanities[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 7051e310..9e0c80c 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -67,6 +67,7 @@ extern const char kOwnerLocale[];
extern const char kDefaultCharset[];
extern const char kAcceptLanguages[];
+extern const char kStaticEncodings[];
extern const char kWebKitCommonScript[];
extern const char kWebKitStandardFontFamily[];
extern const char kWebKitFixedFontFamily[];
@@ -138,6 +146,7 @@ extern const char kWebKitJavascriptCanOpenWindowsAutomatically[];
extern const char kWebKitLoadsImagesAutomatically[];
extern const char kWebKitPluginsEnabled[];
extern const char kWebKitDomPasteEnabled[];
+extern const char kWebKitUsesUniversalDetector[];
extern const char kWebKitTextAreasAreResizable[];
extern const char kWebkitTabsToLinks[];
extern const char kWebKitAllowRunningInsecureContent[];
@@ -302,6 +318,7 @@ extern const char kEolNotificationDismissed[];
extern const char kQuickUnlockFeatureNotificationShown[];
#endif // defined(OS_CHROMEOS)
extern const char kShowHomeButton[];
+extern const char kRecentlySelectedEncoding[];
extern const char kSpeechRecognitionFilterProfanities[];
extern const char kSavingBrowserHistoryDisabled[];
extern const char kAllowDeletingBrowserHistory[];
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index ae86bc7..5da12c5 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2945,6 +2945,16 @@ bool WebContentsImpl::WillNotifyDisconnection() const {
return notify_disconnection_;
}
+void WebContentsImpl::SetOverrideEncoding(const std::string& encoding) {
+ SetEncoding(encoding);
+ Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding));
+}
+
+void WebContentsImpl::ResetOverrideEncoding() {
+ canonical_encoding_.clear();
+ Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID()));
+}
+
RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() {
return &renderer_preferences_;
}
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index f6df8a0..580e40c 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -383,6 +383,8 @@ class CONTENT_EXPORT WebContentsImpl
const base::Callback<void(int64_t)>& callback) override;
const std::string& GetContentsMimeType() const override;
bool WillNotifyDisconnection() const override;
+ void SetOverrideEncoding(const std::string& encoding) override;
+ void ResetOverrideEncoding() override;
RendererPreferences* GetMutableRendererPrefs() override;
void Close() override;
void SystemDragEnded() override;
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index c40d648..d684b5e 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -474,6 +474,13 @@ IPC_MESSAGE_ROUTED2(ViewMsg_SetZoomLevelForLoadingURL,
GURL /* url */,
double /* zoom_level */)
+// Change encoding of page in the renderer.
+IPC_MESSAGE_ROUTED1(ViewMsg_SetPageEncoding,
+ std::string /*new encoding name*/)
+
+// Reset encoding of page in the renderer back to default.
+IPC_MESSAGE_ROUTED0(ViewMsg_ResetPageEncodingToDefault)
+
// Used to tell a render view whether it should expose various bindings
// that allow JS content extended privileges. See BindingsPolicy for valid
// flag values.
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 1eb4d7c..444cb8c 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -580,6 +580,17 @@ class WebContents : public PageNavigator,
// Returns true if this WebContents will notify about disconnection.
virtual bool WillNotifyDisconnection() const = 0;
+ // Override the encoding and reload the page by sending down
+ // ViewMsg_SetPageEncoding to the renderer. |UpdateEncoding| is kinda
+ // the opposite of this, by which 'browser' is notified of
+ // the encoding of the current tab from 'renderer' (determined by
+ // auto-detect, http header, meta, bom detection, etc).
+ virtual void SetOverrideEncoding(const std::string& encoding) = 0;
+
+ // Remove any user-defined override encoding and reload by sending down
+ // ViewMsg_ResetPageEncodingToDefault to the renderer.
+ virtual void ResetOverrideEncoding() = 0;
+
// Returns the settings which get passed to the renderer.
virtual content::RendererPreferences* GetMutableRendererPrefs() = 0;
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index f2eb0d2..acf2889 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -133,6 +133,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(plugins_enabled)
IPC_STRUCT_TRAITS_MEMBER(dom_paste_enabled)
IPC_STRUCT_TRAITS_MEMBER(shrinks_standalone_images_to_fit)
+ IPC_STRUCT_TRAITS_MEMBER(uses_universal_detector)
IPC_STRUCT_TRAITS_MEMBER(text_areas_are_resizable)
IPC_STRUCT_TRAITS_MEMBER(allow_scripts_to_close_windows)
IPC_STRUCT_TRAITS_MEMBER(remote_fonts_enabled)
diff --git a/content/public/common/web_preferences.cc b/content/public/common/web_preferences.cc
index 18a484d..3b96ab9 100644
--- a/content/public/common/web_preferences.cc
+++ b/content/public/common/web_preferences.cc
@@ -82,6 +82,7 @@ WebPreferences::WebPreferences()
plugins_enabled(true),
dom_paste_enabled(false), // enables execCommand("paste")
shrinks_standalone_images_to_fit(true),
+ uses_universal_detector(false), // Disabled: page cycler regression
text_areas_are_resizable(true),
allow_scripts_to_close_windows(false),
remote_fonts_enabled(true),
diff --git a/content/public/common/web_preferences.h b/content/public/common/web_preferences.h
index 5509a57..a486412 100644
--- a/content/public/common/web_preferences.h
+++ b/content/public/common/web_preferences.h
@@ -98,6 +98,7 @@ struct CONTENT_EXPORT WebPreferences {
bool plugins_enabled;
bool dom_paste_enabled;
bool shrinks_standalone_images_to_fit;
+ bool uses_universal_detector;
bool text_areas_are_resizable;
bool allow_scripts_to_close_windows;
bool remote_fonts_enabled;
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 9aefa5e..42cf022 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -960,6 +960,7 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->setImagesEnabled(prefs.images_enabled);
settings->setPluginsEnabled(prefs.plugins_enabled);
settings->setDOMPasteAllowed(prefs.dom_paste_enabled);
+ settings->setUsesEncodingDetector(prefs.uses_universal_detector);
settings->setTextAreasAreResizable(prefs.text_areas_are_resizable);
settings->setAllowScriptsToCloseWindows(prefs.allow_scripts_to_close_windows);
settings->setDownloadableBinaryFontsEnabled(prefs.remote_fonts_enabled);
@@ -1321,6 +1329,9 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingURL,
OnSetZoomLevelForLoadingURL)
+ IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
+ IPC_MESSAGE_HANDLER(ViewMsg_ResetPageEncodingToDefault,
+ OnResetPageEncodingToDefault)
IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter)
IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver)
IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave, OnDragTargetDragLeave)
@@ -2279,6 +2297,15 @@ void RenderViewImpl::OnSetZoomLevel(
SetZoomLevel(zoom_level);
}
+void RenderViewImpl::OnSetPageEncoding(const std::string& encoding_name) {
+ webview()->setPageEncoding(WebString::fromUTF8(encoding_name));
+}
+
+void RenderViewImpl::OnResetPageEncodingToDefault() {
+ WebString no_encoding;
+ webview()->setPageEncoding(no_encoding);
+}
+
void RenderViewImpl::OnAllowBindings(int enabled_bindings_flags) {
if ((enabled_bindings_flags & BINDINGS_POLICY_WEB_UI) &&
!(enabled_bindings_ & BINDINGS_POLICY_WEB_UI)) {
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 4944cab..1cfd65b 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -602,11 +602,13 @@ class CONTENT_EXPORT RenderViewImpl
const blink::WebPluginAction& action);
void OnMoveOrResizeStarted();
void OnReleaseDisambiguationPopupBitmap(const cc::SharedBitmapId& id);
+ void OnResetPageEncodingToDefault();
void OnSetActive(bool active);
void OnSetBackgroundOpaque(bool opaque);
void OnExitFullscreen();
void OnSetHistoryOffsetAndLength(int history_offset, int history_length);
void OnSetInitialFocus(bool reverse);
+ void OnSetPageEncoding(const std::string& encoding_name);
void OnSetRendererPrefs(const RendererPreferences& renderer_prefs);
void OnSetWebUIProperty(const std::string& name, const std::string& value);
void OnSetZoomLevelForLoadingURL(const GURL& url, double zoom_level);
diff --git a/third_party/WebKit/Source/core/frame/FrameHost.h b/third_party/WebKit/Source/core/frame/FrameHost.h
index c8282b2..c909e69 100644
--- a/third_party/WebKit/Source/core/frame/FrameHost.h
+++ b/third_party/WebKit/Source/core/frame/FrameHost.h
@@ -115,6 +115,9 @@ class CORE_EXPORT FrameHost final
EventHandlerRegistry& eventHandlerRegistry();
const EventHandlerRegistry& eventHandlerRegistry() const;
+ const AtomicString& overrideEncoding() const { return m_overrideEncoding; }
+ void setOverrideEncoding(const AtomicString& encoding) { m_overrideEncoding = encoding; }
+
ConsoleMessageStorage& consoleMessageStorage();
const ConsoleMessageStorage& consoleMessageStorage() const;
diff --git a/third_party/WebKit/Source/core/frame/Settings.in b/third_party/WebKit/Source/core/frame/Settings.in
index 2d94517..0adcba6 100644
--- a/third_party/WebKit/Source/core/frame/Settings.in
+++ b/third_party/WebKit/Source/core/frame/Settings.in
@@ -71,6 +71,7 @@ textAreasAreResizable initial=false, invalidate=Style
acceleratedCompositingEnabled initial=true, invalidate=AcceleratedCompositing
offlineWebApplicationCacheEnabled initial=true
+usesEncodingDetector initial=false
allowScriptsToCloseWindows initial=false
# FIXME: This should really be disabled by default as it makes platforms that
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
index 0941688..617959a 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -473,7 +473,7 @@ void DocumentLoader::ensureWriter(const AtomicString& mimeType,
if (m_writer)
return;
- const AtomicString& encoding = response().textEncodingName();
+ const AtomicString& encoding = m_frame->host()->overrideEncoding().isNull() ? response().textEncodingName() : m_frame->host()->overrideEncoding();
// Prepare a DocumentInit before clearing the frame, because it may need to
// inherit an aliased security context.
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index aa986da..e17f0c7 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -307,6 +307,8 @@ WebCachePolicy FrameFetchContext::resourceRequestCachePolicy(
if (request.httpMethod() == "POST" &&
frameLoadType == FrameLoadTypeBackForward)
return WebCachePolicy::ReturnCacheDataDontLoad;
+ if (!frame()->host()->overrideEncoding().isEmpty())
+ return WebCachePolicy::ReturnCacheDataElseLoad;
if (frameLoadType == FrameLoadTypeReloadMainResource ||
request.isConditional() || request.httpMethod() == "POST")
return WebCachePolicy::ValidatingCacheData;
diff --git a/third_party/WebKit/Source/web/WebSettingsImpl.cpp b/third_party/WebKit/Source/web/WebSettingsImpl.cpp
index 14c6ff8..ee014a7 100644
--- a/third_party/WebKit/Source/web/WebSettingsImpl.cpp
+++ b/third_party/WebKit/Source/web/WebSettingsImpl.cpp
@@ -312,6 +312,10 @@ void WebSettingsImpl::setSpatialNavigationEnabled(bool enabled) {
m_settings->setSpatialNavigationEnabled(enabled);
}
+void WebSettingsImpl::setUsesEncodingDetector(bool usesDetector) {
+ m_settings->setUsesEncodingDetector(usesDetector);
+}
+
void WebSettingsImpl::setSpellCheckEnabledByDefault(bool enabled) {
m_settings->setSpellCheckEnabledByDefault(enabled);
}
diff --git a/third_party/WebKit/Source/web/WebSettingsImpl.h b/third_party/WebKit/Source/web/WebSettingsImpl.h
index 4cc8754..ef0ef2e 100644
--- a/third_party/WebKit/Source/web/WebSettingsImpl.h
+++ b/third_party/WebKit/Source/web/WebSettingsImpl.h
@@ -190,6 +190,7 @@ class WEB_EXPORT WebSettingsImpl final
void setViewportStyle(WebViewportStyle) override;
void setUseSolidColorScrollbars(bool) override;
void setUseWideViewport(bool) override;
+ void setUsesEncodingDetector(bool) override;
void setV8CacheOptions(V8CacheOptions) override;
void setV8CacheStrategiesForCacheStorage(
V8CacheStrategiesForCacheStorage) override;
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index 6c8ca56..16ea6f9 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -3011,6 +3011,29 @@ WebString WebViewImpl::pageEncoding() const {
return m_page->deprecatedLocalMainFrame()->document()->encodingName();
}
+void WebViewImpl::setPageEncoding(const WebString& encodingName) {
+ if (!m_page)
+ return;
+
+ // Only change override encoding, don't change default encoding.
+ // Note that the new encoding must be 0 if it isn't supposed to be set.
+ AtomicString newEncodingName;
+ if (!encodingName.isEmpty())
+ newEncodingName = encodingName;
+ m_page->frameHost().setOverrideEncoding(newEncodingName);
+
+ if (m_page->mainFrame()->isLocalFrame()) {
+ if (!m_page->deprecatedLocalMainFrame()->loader().currentItem())
+ return;
+ FrameLoadRequest request = FrameLoadRequest(
+ nullptr,
+ m_page->deprecatedLocalMainFrame()->loader().resourceRequestForReload(
+ FrameLoadTypeReload, KURL(), ClientRedirectPolicy::ClientRedirect));
+ request.setClientRedirect(ClientRedirectPolicy::ClientRedirect);
+ m_page->deprecatedLocalMainFrame()->loader().load(request, FrameLoadTypeReload);
+ }
+}
+
WebFrame* WebViewImpl::mainFrame() {
return WebFrame::fromFrame(m_page ? m_page->mainFrame() : nullptr);
}
diff --git a/third_party/WebKit/Source/web/WebViewImpl.h b/third_party/WebKit/Source/web/WebViewImpl.h
index 238b096..5b08e61 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.h
+++ b/third_party/WebKit/Source/web/WebViewImpl.h
@@ -169,6 +169,7 @@ class WEB_EXPORT WebViewImpl final
void setSpellCheckClient(WebSpellCheckClient*) override;
WebSettings* settings() override;
WebString pageEncoding() const override;
+ void setPageEncoding(const WebString&) override;
bool tabsToLinks() const override;
void setTabsToLinks(bool value) override;
bool tabKeyCyclesThroughElements() const override;
diff --git a/third_party/WebKit/public/web/WebSettings.h b/third_party/WebKit/public/web/WebSettings.h
index eafe8d4..419eabab 100644
--- a/third_party/WebKit/public/web/WebSettings.h
+++ b/third_party/WebKit/public/web/WebSettings.h
@@ -276,6 +276,7 @@ class WebSettings {
virtual void setViewportStyle(WebViewportStyle) = 0;
virtual void setUseSolidColorScrollbars(bool) = 0;
virtual void setUseWideViewport(bool) = 0;
+ virtual void setUsesEncodingDetector(bool) = 0;
virtual void setV8CacheOptions(V8CacheOptions) = 0;
virtual void setV8CacheStrategiesForCacheStorage(
V8CacheStrategiesForCacheStorage) = 0;
diff --git a/third_party/WebKit/public/web/WebView.h b/third_party/WebKit/public/web/WebView.h
index d877ff0..75c4d49 100644
--- a/third_party/WebKit/public/web/WebView.h
+++ b/third_party/WebKit/public/web/WebView.h
@@ -147,6 +147,7 @@ class WebView : protected WebWidget {
// Corresponds to the encoding of the main frame. Setting the page
// encoding may cause the main frame to reload.
virtual WebString pageEncoding() const = 0;
+ virtual void setPageEncoding(const WebString&) = 0;
// Controls whether pressing Tab key advances focus to links.
virtual bool tabsToLinks() const = 0;
@msr-i386
Copy link
Author

このパッチは、Chromium 55.0.2883.87のソースコードからgit applyで適用できます。
動作保証は致しかねますので、パッチを適用の際は各自の責任の下で十分なテストを行うことを強く推奨します。
Chromiumの開発者の迷惑になるので、Chromiumにこのパッチを送らないでください。

このパッチを適用の上ビルドしたバイナリを不特定多数に公開する場合は、事後でもかまいませんのでMSR (TwitterID: @msr386)まで声をかけていただけるとうれしいです。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment