|
|
@@ -0,0 +1,184 @@
|
|
|
+/**
|
|
|
+ * 页面编码集
|
|
|
+ * @author zhaoxianlie
|
|
|
+ */
|
|
|
+"use strict";
|
|
|
+
|
|
|
+let PageEncoding = (() => {
|
|
|
+
|
|
|
+ // 某Tab的编码都暂存一下,这是prefix
|
|
|
+ const ENCODING_PREFIX = 'FE_ENCODING_PREFIX_';
|
|
|
+
|
|
|
+ // 系统支持的编码列表
|
|
|
+ let EncodingList = [
|
|
|
+ ['default', '默认'],
|
|
|
+ ['UTF-8', 'Unicode'],
|
|
|
+ ['GBK', '中文(简体全)'],
|
|
|
+ ['GB3212', '中文(简体)'],
|
|
|
+ ['GB18030', '中文(简体)'],
|
|
|
+ ['Big5', '中文(繁体)'],
|
|
|
+ ['UTF-16LE', 'Unicode'],
|
|
|
+ ['EUC-KR', '韩文'],
|
|
|
+ ['Shift_JIS', '日文'],
|
|
|
+ ['EUC-JP', '日文'],
|
|
|
+ ['ISO-2022-JP', '日文'],
|
|
|
+ ['Windows-874', '泰文'],
|
|
|
+ ['Windows-1254', '土耳其文'],
|
|
|
+ ['ISO-8859-7', '希腊文'],
|
|
|
+ ['Windows-1253', '希腊文'],
|
|
|
+ ['Windows-1252', '西文'],
|
|
|
+ ['ISO-8859-15', '西文'],
|
|
|
+ ['Macintosh', '西文'],
|
|
|
+ ['Windows-1258', '越南文'],
|
|
|
+ ['ISO-8859-2', '中欧文'],
|
|
|
+ ['Windows-1250', '中欧文']
|
|
|
+ ];
|
|
|
+
|
|
|
+
|
|
|
+ // 菜单列表
|
|
|
+ let menuMap = {};
|
|
|
+ // 监听是否已经加过了
|
|
|
+ let listenerAddedFlag = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建右键菜单
|
|
|
+ */
|
|
|
+ let createMenu = (parentMenuId) => {
|
|
|
+
|
|
|
+ let encodingMenu = chrome.contextMenus.create({
|
|
|
+ title: "♨ 网页编码设置",
|
|
|
+ contexts: ["all"],
|
|
|
+ documentUrlPatterns: ['http://*/*', 'https://*/*', 'file://*/*'],
|
|
|
+ parentId: parentMenuId
|
|
|
+ });
|
|
|
+
|
|
|
+ EncodingList.forEach(item => {
|
|
|
+ menuMap[item[0].toUpperCase()] = chrome.contextMenus.create({
|
|
|
+ type: "radio",
|
|
|
+ contexts: ["all"],
|
|
|
+ title: item[0] === 'default' ? '默认' : `${item[1]}(${item[0]})`,
|
|
|
+ checked: item[0] === 'default',
|
|
|
+ parentId: encodingMenu,
|
|
|
+ onclick: (info, tab) => {
|
|
|
+ if (!info.wasChecked) {
|
|
|
+ if (item[0] === 'default') {
|
|
|
+ localStorage.removeItem(ENCODING_PREFIX + tab.id);
|
|
|
+ } else {
|
|
|
+ localStorage.setItem(ENCODING_PREFIX + tab.id, item[0]);
|
|
|
+ }
|
|
|
+ if (!listenerAddedFlag) {
|
|
|
+ addOnlineSiteEncodingListener((granted) => {
|
|
|
+ if (granted) {
|
|
|
+ chrome.tabs.reload(tab.id, {
|
|
|
+ bypassCache: true
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ chrome.tabs.reload(tab.id, {
|
|
|
+ bypassCache: true
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新菜单的选中状态
|
|
|
+ * @param tabId
|
|
|
+ */
|
|
|
+ let updateMenu = (tabId) => {
|
|
|
+ Object.keys(menuMap).forEach(menu => {
|
|
|
+ chrome.contextMenus.update(menuMap[menu], {
|
|
|
+ checked: false
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 选中它该选中的
|
|
|
+ let encoding = localStorage.getItem(ENCODING_PREFIX + tabId) || '';
|
|
|
+ let menuId = encoding ? menuMap[encoding.toUpperCase()] : menuMap['DEFAULT'];
|
|
|
+ chrome.contextMenus.update(menuId || menuMap['DEFAULT'], {
|
|
|
+ checked: true
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * web请求截获,重置response Headers
|
|
|
+ * @param callback
|
|
|
+ */
|
|
|
+ let addOnlineSiteEncodingListener = (callback) => {
|
|
|
+ // 请求权限
|
|
|
+ chrome.permissions.request({
|
|
|
+ permissions: ['webRequest', 'webRequestBlocking']
|
|
|
+ }, (granted) => {
|
|
|
+ if (granted) {
|
|
|
+ listenerAddedFlag = true;
|
|
|
+ chrome.webRequest.onHeadersReceived.addListener((details) => {
|
|
|
+ let tabEncoding = localStorage.getItem(ENCODING_PREFIX + details.tabId);
|
|
|
+
|
|
|
+ if (tabEncoding) {
|
|
|
+ let i, charsetPattern = /; ?charset=([^;]+)/;
|
|
|
+ for (i = 0; i < details.responseHeaders.length; ++i) {
|
|
|
+ if (details.responseHeaders[i].name.toLowerCase() === 'content-type') {
|
|
|
+ let value = details.responseHeaders[i].value.toLowerCase();
|
|
|
+ if (
|
|
|
+ value.startsWith('text') ||
|
|
|
+ value.startsWith('application/javascript') ||
|
|
|
+ value.startsWith('application/x-javascript') ||
|
|
|
+ value.startsWith('application/json')
|
|
|
+ ) {
|
|
|
+ if (charsetPattern.test(value)) {
|
|
|
+ value = value.replace(charsetPattern.exec(value)[1], tabEncoding);
|
|
|
+ } else {
|
|
|
+ value += value.substr(-1) === ';' ? ' ' : '; ';
|
|
|
+ value += 'charset=' + tabEncoding;
|
|
|
+ }
|
|
|
+ details.responseHeaders[i].value = value;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (i >= details.responseHeaders.length) {
|
|
|
+ details.responseHeaders.push({
|
|
|
+ name: 'Content-Type',
|
|
|
+ value: 'text/plain; charset=' + tabEncoding
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {responseHeaders: details.responseHeaders};
|
|
|
+ }, {urls: ["<all_urls>"]}, ["responseHeaders", "blocking"]);
|
|
|
+ } else {
|
|
|
+ alert('必须接受授权,才能正常使用!');
|
|
|
+ }
|
|
|
+ callback && callback(granted);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 标签被关闭时的检测
|
|
|
+ chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
|
|
|
+ localStorage.removeItem(ENCODING_PREFIX + tabId);
|
|
|
+ });
|
|
|
+ // 标签页有切换时
|
|
|
+ chrome.tabs.onActivated.addListener((activeInfo) => {
|
|
|
+ if (Object.keys(menuMap).length) {
|
|
|
+ updateMenu(activeInfo.tabId);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ chrome.windows.onFocusChanged.addListener(() => {
|
|
|
+ if (Object.keys(menuMap).length) {
|
|
|
+ chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
|
|
|
+ if (tabs.length) {
|
|
|
+ updateMenu(tabs[0].id);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ return {
|
|
|
+ createMenu
|
|
|
+ };
|
|
|
+
|
|
|
+})();
|