awesome.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /**
  2. * 工具更新
  3. * @type {{download}}
  4. */
  5. import toolMap from './tools.js';
  6. import MSG_TYPE from '../static/js/common.js';
  7. let Awesome = (() => {
  8. let manifest = chrome.runtime.getManifest();
  9. const SERVER_SITE = manifest.homepage_url;
  10. const URL_TOOL_TPL = `${SERVER_SITE}/#TOOL-NAME#/index.html`;
  11. const TOOL_NAME_TPL = 'DYNAMIC_TOOL:#TOOL-NAME#';
  12. const TOOL_CONTENT_SCRIPT_TPL = 'DYNAMIC_TOOL:CS:#TOOL-NAME#';
  13. const TOOL_CONTENT_SCRIPT_CSS_TPL = 'DYNAMIC_TOOL:CS:CSS:#TOOL-NAME#';
  14. const TOOL_MENU_TPL = 'DYNAMIC_MENU:#TOOL-NAME#';
  15. /**
  16. * 管理本地存储
  17. */
  18. let StorageMgr = (() => {
  19. let get = keyArr => {
  20. return new Promise((resolve, reject) => {
  21. chrome.storage.local.get(keyArr, result => {
  22. resolve(typeof keyArr === 'string' ? result[keyArr] : result);
  23. });
  24. });
  25. };
  26. let getSync = async (keyArr) => {
  27. return await (new Promise((resolve, reject) => {
  28. chrome.storage.local.get(keyArr, result => {
  29. resolve(typeof keyArr === 'string' ? result[keyArr] : result);
  30. });
  31. }));
  32. };
  33. let set = (items, values) => {
  34. return new Promise((resolve, reject) => {
  35. if (typeof items === 'string') {
  36. let tmp = {};
  37. tmp[items] = values;
  38. items = tmp;
  39. }
  40. chrome.storage.local.set(items, () => {
  41. resolve();
  42. });
  43. });
  44. };
  45. let remove = keyArr => {
  46. return new Promise((resolve, reject) => {
  47. keyArr = [].concat(keyArr);
  48. chrome.storage.local.remove(keyArr, () => {
  49. resolve();
  50. });
  51. });
  52. };
  53. return {get, set, remove,getSync};
  54. })();
  55. /**
  56. * 检测工具是否已被成功安装
  57. * @param toolName 工具名称
  58. * @param detectMenu 是否进一步检测Menu的设置情况
  59. * @returns {Promise}
  60. */
  61. let detectInstall = (toolName, detectMenu) => {
  62. let menuKey = TOOL_MENU_TPL.replace('#TOOL-NAME#', toolName);
  63. let toolKey = TOOL_NAME_TPL.replace('#TOOL-NAME#', toolName);
  64. return Promise.all([StorageMgr.get(toolKey), StorageMgr.get(menuKey)]).then(values => {
  65. if (detectMenu) {
  66. return values[0] && String(values[1]) === '1';
  67. }
  68. return !!values[0];
  69. });
  70. };
  71. let log = (txt) => {
  72. // console.log(String(new Date(new Date() * 1 - (new Date().getTimezoneOffset()) * 60 * 1000).toJSON()).replace(/T/i, ' ').replace(/Z/i, '') + '>', txt);
  73. };
  74. /**
  75. * 安装/更新工具,支持显示安装进度
  76. * @param toolName
  77. * @param fnProgress
  78. * @returns {Promise<any>}
  79. */
  80. let install = (toolName, fnProgress) => {
  81. return new Promise((resolve, reject) => {
  82. // 存储html文件
  83. StorageMgr.set(TOOL_NAME_TPL.replace('#TOOL-NAME#', toolName), '&nbsp;');
  84. log(toolName + '工具html模板安装/更新成功!');
  85. resolve();
  86. });
  87. };
  88. let offLoad = (toolName) => {
  89. let items = [];
  90. items.push(TOOL_NAME_TPL.replace('#TOOL-NAME#', toolName));
  91. items.push(TOOL_CONTENT_SCRIPT_TPL.replace('#TOOL-NAME#', toolName));
  92. items.push(TOOL_CONTENT_SCRIPT_CSS_TPL.replace('#TOOL-NAME#', toolName));
  93. // 删除所有静态文件
  94. chrome.storage.local.get(null, allDatas => {
  95. StorageMgr.remove(Object.keys(allDatas).filter(key => String(key).startsWith(`../${toolName}/`)));
  96. });
  97. log(toolName + ' 卸载成功!');
  98. return StorageMgr.remove(items);
  99. };
  100. /**
  101. * 有些工具其实已经卸载过了,但是本地还有冗余的静态文件,都需要统一清理一遍
  102. */
  103. let gcLocalFiles = () => getAllTools().then(tools => Object.keys(tools).forEach(tool => {
  104. if (!tools[tool]._devTool && !tools[tool].installed) {
  105. offLoad(tool);
  106. }
  107. }));
  108. let getAllTools = async () => {
  109. // 获取本地开发的插件,也拼接进来
  110. try {
  111. const DEV_TOOLS_MY_TOOLS = 'DEV-TOOLS:MY-TOOLS';
  112. let _tools = await StorageMgr.getSync(DEV_TOOLS_MY_TOOLS);
  113. let localDevTools = JSON.parse(_tools || '{}');
  114. Object.keys(localDevTools).forEach(tool => {
  115. toolMap[tool] = localDevTools[tool];
  116. });
  117. } catch (e) {
  118. }
  119. let tools = Object.keys(toolMap);
  120. let promises = [];
  121. tools.forEach(tool => {
  122. promises = promises.concat([detectInstall(tool), detectInstall(tool, true)])
  123. });
  124. let pAll = Promise.all(promises).then(values => {
  125. values.forEach((v, i) => {
  126. let tool = tools[Math.floor(i / 2)];
  127. let key = i % 2 === 0 ? 'installed' : 'menu';
  128. toolMap[tool][key] = v;
  129. // 本地工具,还需要看是否处于开启状态
  130. if (toolMap[tool].hasOwnProperty('_devTool')) {
  131. toolMap[tool][key] = toolMap[tool][key] && toolMap[tool]._enable;
  132. }
  133. });
  134. Object.keys(toolMap).forEach(tool => {
  135. toolMap[tool].installed = toolMap[tool].systemInstalled || toolMap[tool].installed;
  136. });
  137. return toolMap;
  138. });
  139. let pSort = SortToolMgr.get();
  140. return Promise.all([pAll,pSort]).then(vs => {
  141. let allTools = vs[0];
  142. let sortTools = vs[1];
  143. if (sortTools && sortTools.length) {
  144. let map = {};
  145. sortTools.forEach(tool => {
  146. map[tool] = allTools[tool];
  147. });
  148. Object.keys(allTools).forEach(tool => {
  149. if (!map[tool]) {
  150. map[tool] = allTools[tool];
  151. }
  152. });
  153. return map;
  154. }else{
  155. return allTools;
  156. }
  157. });
  158. };
  159. /**
  160. * 检查看本地已安装过哪些工具
  161. * @returns {Promise}
  162. */
  163. let getInstalledTools = () => getAllTools().then(tools => {
  164. let istTolls = {};
  165. Object.keys(tools).filter(tool => {
  166. if (tools[tool] && tools[tool].installed) {
  167. istTolls[tool] = tools[tool];
  168. }
  169. });
  170. return istTolls;
  171. });
  172. /**
  173. * 获取工具的content-script
  174. * @param toolName
  175. * @param cssMode
  176. */
  177. let getContentScript = (toolName, cssMode) => {
  178. return StorageMgr.get(cssMode ? TOOL_CONTENT_SCRIPT_CSS_TPL.replace('#TOOL-NAME#', toolName)
  179. : TOOL_CONTENT_SCRIPT_TPL.replace('#TOOL-NAME#', toolName));
  180. };
  181. /**
  182. * 获取工具的html模板
  183. * @param toolName
  184. * @returns {*}
  185. */
  186. let getToolTpl = (toolName) => StorageMgr.get(TOOL_NAME_TPL.replace('#TOOL-NAME#', toolName));
  187. /**
  188. * 从服务器检查,看本地已安装的工具,有哪些又已经升级过了
  189. * @param tool
  190. */
  191. let checkUpgrade = (tool) => {
  192. let getOnline = (toolName) => fetch(URL_TOOL_TPL.replace('#TOOL-NAME#', toolName)).then(resp => resp.text());
  193. let getOffline = (toolName) => StorageMgr.get(TOOL_NAME_TPL.replace('#TOOL-NAME#', toolName));
  194. return Promise.all([getOnline(tool), getOffline(tool)]).then(values => {
  195. let onlineData = _tplHandler(tool, values[0]);
  196. let local = values[1];
  197. return local !== onlineData.html;
  198. });
  199. };
  200. /**
  201. * 管理右键菜单
  202. * @param toolName
  203. * @param action 具体动作install/offload/get
  204. * @returns {Promise<any>}
  205. */
  206. let menuMgr = (toolName, action) => {
  207. let menuKey = TOOL_MENU_TPL.replace('#TOOL-NAME#', toolName);
  208. switch (action) {
  209. case 'get':
  210. return StorageMgr.get(menuKey);
  211. case 'offload':
  212. // 必须用setItem模式,而不是removeItem,要处理 0/1/null三种结果
  213. log(toolName + ' 卸载成功!');
  214. return StorageMgr.set(menuKey, 0);
  215. case 'install':
  216. log(toolName + ' 安装成功!');
  217. return StorageMgr.set(menuKey, 1);
  218. }
  219. };
  220. /**
  221. * 远程获取的代码管理器
  222. * @type {{get, set}}
  223. */
  224. let CodeCacheMgr = (() => {
  225. const TOOLS_FROM_REMOTE = 'TOOLS_FROM_REMOTE';
  226. let get = () => {
  227. return StorageMgr.getSync(TOOLS_FROM_REMOTE);
  228. };
  229. let set = (remoteCodes) => {
  230. let obj = {};
  231. obj[TOOLS_FROM_REMOTE]=remoteCodes;
  232. chrome.storage.local.set(obj);
  233. };
  234. return {get, set};
  235. })();
  236. /**
  237. * 工具排序管理器
  238. * @type {{get, set}}
  239. */
  240. let SortToolMgr = (() => {
  241. const TOOLS_CUSTOM_SORT = 'TOOLS_CUSTOM_SORT';
  242. let get = async () => {
  243. let cache = await StorageMgr.getSync(TOOLS_CUSTOM_SORT);
  244. return [].concat(JSON.parse(cache || '[]')).filter(t => !!t);
  245. };
  246. let set = (newSortArray) => {
  247. let obj = {};
  248. obj[TOOLS_CUSTOM_SORT] = JSON.stringify([].concat(newSortArray || []).filter(t => !!t));
  249. chrome.storage.local.set(obj);
  250. };
  251. return {get, set};
  252. })();
  253. return {
  254. StorageMgr,
  255. detectInstall,
  256. install,
  257. offLoad,
  258. getInstalledTools,
  259. menuMgr,
  260. checkUpgrade,
  261. getContentScript,
  262. getToolTpl,
  263. gcLocalFiles,
  264. getAllTools,
  265. SortToolMgr,
  266. CodeCacheMgr
  267. }
  268. })();
  269. export default Awesome;