1
0

index.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /**
  2. * 页面编码集
  3. * @author zhaoxianlie
  4. */
  5. "use strict";
  6. let PageEncoding = (() => {
  7. // 某Tab的编码都暂存一下,这是prefix
  8. const ENCODING_PREFIX = 'FE_ENCODING_PREFIX_';
  9. // 系统支持的编码列表
  10. let EncodingList = [
  11. ['default', '默认'],
  12. ['UTF-8', 'Unicode'],
  13. ['GBK', '简体中文'],
  14. ['GB3212', '简体中文'],
  15. ['GB18030', '简体中文'],
  16. ['Big5', '繁体中文'],
  17. ['UTF-16LE', 'Unicode'],
  18. ['EUC-KR', '韩文'],
  19. ['Shift_JIS', '日文'],
  20. ['EUC-JP', '日文'],
  21. ['ISO-2022-JP', '日文'],
  22. ['Windows-874', '泰文'],
  23. ['Windows-1254', '土耳其文'],
  24. ['ISO-8859-7', '希腊文'],
  25. ['Windows-1253', '希腊文'],
  26. ['Windows-1252', '西文'],
  27. ['ISO-8859-15', '西文'],
  28. ['Macintosh', '西文'],
  29. ['Windows-1258', '越南文'],
  30. ['ISO-8859-2', '中欧文'],
  31. ['Windows-1250', '中欧文']
  32. ];
  33. // 菜单列表
  34. let menuMap = {};
  35. // 监听是否已经加过了
  36. let listenerAddedFlag = false;
  37. /**
  38. * 创建右键菜单
  39. */
  40. let createMenu = (parentMenuId, menuConfig) => {
  41. let encodingMenu = chrome.contextMenus.create({
  42. title: menuConfig.icon + ' ' + menuConfig.text,
  43. contexts: menuConfig.contexts || ["all"],
  44. documentUrlPatterns: ['http://*/*', 'https://*/*', 'file://*/*'],
  45. parentId: parentMenuId
  46. });
  47. EncodingList.forEach(item => {
  48. menuMap[item[0].toUpperCase()] = chrome.contextMenus.create({
  49. type: "radio",
  50. contexts: ["all"],
  51. title: item[0] === 'default' ? '默认' : `${item[1]}(${item[0]})`,
  52. checked: item[0] === 'default',
  53. parentId: encodingMenu,
  54. onclick: (info, tab) => {
  55. if (!info.wasChecked) {
  56. if (item[0] === 'default') {
  57. localStorage.removeItem(ENCODING_PREFIX + tab.id);
  58. } else {
  59. localStorage.setItem(ENCODING_PREFIX + tab.id, item[0]);
  60. }
  61. if (!listenerAddedFlag) {
  62. addOnlineSiteEncodingListener((granted) => {
  63. if (granted) {
  64. chrome.tabs.reload(tab.id, {
  65. bypassCache: true
  66. });
  67. }
  68. });
  69. } else {
  70. chrome.tabs.reload(tab.id, {
  71. bypassCache: true
  72. });
  73. }
  74. }
  75. }
  76. });
  77. });
  78. };
  79. /**
  80. * 更新菜单的选中状态
  81. * @param tabId
  82. */
  83. let updateMenu = (tabId) => {
  84. Object.keys(menuMap).forEach(menu => {
  85. chrome.contextMenus.update(menuMap[menu], {
  86. checked: false
  87. });
  88. });
  89. // 选中它该选中的
  90. let encoding = localStorage.getItem(ENCODING_PREFIX + tabId) || '';
  91. let menuId = encoding ? menuMap[encoding.toUpperCase()] : menuMap['DEFAULT'];
  92. chrome.contextMenus.update(menuId || menuMap['DEFAULT'], {
  93. checked: true
  94. });
  95. };
  96. /**
  97. * web请求截获,重置response Headers
  98. * @param callback
  99. */
  100. let addOnlineSiteEncodingListener = (callback) => {
  101. // 请求权限
  102. chrome.permissions.request({
  103. permissions: ['webRequest', 'webRequestBlocking']
  104. }, (granted) => {
  105. if (granted) {
  106. listenerAddedFlag = true;
  107. chrome.webRequest.onHeadersReceived.addListener((details) => {
  108. let tabEncoding = localStorage.getItem(ENCODING_PREFIX + details.tabId);
  109. if (tabEncoding) {
  110. let i, charsetPattern = /; ?charset=([^;]+)/;
  111. for (i = 0; i < details.responseHeaders.length; ++i) {
  112. if (details.responseHeaders[i].name.toLowerCase() === 'content-type') {
  113. let value = details.responseHeaders[i].value.toLowerCase();
  114. if (
  115. value.startsWith('text') ||
  116. value.startsWith('application/javascript') ||
  117. value.startsWith('application/x-javascript') ||
  118. value.startsWith('application/json')
  119. ) {
  120. if (charsetPattern.test(value)) {
  121. value = value.replace(charsetPattern.exec(value)[1], tabEncoding);
  122. } else {
  123. value += value.substr(-1) === ';' ? ' ' : '; ';
  124. value += 'charset=' + tabEncoding;
  125. }
  126. details.responseHeaders[i].value = value;
  127. }
  128. break;
  129. }
  130. }
  131. if (i >= details.responseHeaders.length) {
  132. details.responseHeaders.push({
  133. name: 'Content-Type',
  134. value: 'text/plain; charset=' + tabEncoding
  135. });
  136. }
  137. }
  138. return {responseHeaders: details.responseHeaders};
  139. }, {urls: ["<all_urls>"]}, ["responseHeaders", "blocking"]);
  140. } else {
  141. alert('必须接受授权,才能正常使用!');
  142. }
  143. callback && callback(granted);
  144. });
  145. // 标签被关闭时的检测
  146. chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
  147. localStorage.removeItem(ENCODING_PREFIX + tabId);
  148. });
  149. // 标签页有切换时
  150. chrome.tabs.onActivated.addListener((activeInfo) => {
  151. if (Object.keys(menuMap).length) {
  152. updateMenu(activeInfo.tabId);
  153. }
  154. });
  155. };
  156. return {
  157. createMenu
  158. };
  159. })();