fe-background.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. /**
  2. * FE-Helper后台运行程序
  3. * @author [email protected]
  4. */
  5. var BgPageInstance = (function () {
  6. //各种元素的就绪情况
  7. var _readyState = {
  8. css: false,
  9. js: false,
  10. html: true,
  11. allDone: false
  12. };
  13. /**
  14. * 文本格式,可以设置一个图标和标题
  15. * @param {Object} options
  16. * @config {string} type notification的类型,可选值:html、text
  17. * @config {string} icon 图标
  18. * @config {string} title 标题
  19. * @config {string} message 内容
  20. */
  21. var notifyText = function (options) {
  22. if (!window.Notification) {
  23. return;
  24. }
  25. if (!options.icon) {
  26. options.icon = "static/img/fe-48.png";
  27. }
  28. if (!options.title) {
  29. options.title = "温馨提示";
  30. }
  31. return chrome.notifications.create('', {
  32. type: 'basic',
  33. title: options.title,
  34. iconUrl: chrome.runtime.getURL(options.icon),
  35. message: options.message
  36. });
  37. };
  38. //侦测就绪情况
  39. var _detectReadyState = function (callback) {
  40. if (_readyState.css && _readyState.js && _readyState.html) {
  41. _readyState.allDone = true;
  42. }
  43. if(_readyState.allDone && typeof callback == 'function'){
  44. callback();
  45. }
  46. };
  47. var _fcp_detect_interval = [];
  48. /**
  49. * 执行前端FCPHelper检测
  50. */
  51. var _doFcpDetect = function (tab) {
  52. //所有元素都准备就绪
  53. if (_readyState.allDone) {
  54. clearInterval(_fcp_detect_interval[tab.id]);
  55. chrome.tabs.sendMessage(tab.id, {
  56. type: MSG_TYPE.BROWSER_CLICKED,
  57. event: MSG_TYPE.FCP_HELPER_DETECT
  58. });
  59. } else if(_fcp_detect_interval[tab.id] === undefined) {
  60. chrome.tabs.sendMessage(tab.id, {
  61. type: MSG_TYPE.BROWSER_CLICKED,
  62. event: MSG_TYPE.FCP_HELPER_INIT
  63. });
  64. //显示桌面提醒
  65. notifyText({
  66. message: "正在准备数据,请稍等..."
  67. });
  68. _fcp_detect_interval[tab.id] = setInterval(function(){
  69. _doFcpDetect(tab);
  70. },200);
  71. }
  72. };
  73. /**
  74. * 查看页面wpo信息
  75. */
  76. var _showPageWpoInfo = function (wpoInfo) {
  77. chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
  78. if (!wpoInfo) {
  79. notifyText({
  80. message: "对不起,检测失败"
  81. });
  82. } else {
  83. chrome.tabs.create({
  84. url: "template/fehelper_wpo.html?" + btoa(encodeURIComponent(JSON.stringify(wpoInfo))),
  85. active: true
  86. });
  87. }
  88. });
  89. };
  90. /**
  91. * 获取页面wpo信息
  92. * @return {[type]}
  93. */
  94. var _getPageWpoInfo = function () {
  95. chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
  96. var tab = tabs[0];
  97. //显示桌面提醒
  98. chrome.tabs.sendMessage(tab.id, {
  99. type: MSG_TYPE.GET_PAGE_WPO_INFO
  100. });
  101. });
  102. };
  103. /**
  104. * 代码压缩工具
  105. * @private
  106. */
  107. var _goCompressTool = function () {
  108. var url = "http://www.baidufe.com/fehelper/codecompress.html";
  109. chrome.tabs.query({windowId: chrome.windows.WINDOW_ID_CURRENT}, function (tabs) {
  110. var isOpened = false;
  111. var tabId;
  112. var reg = new RegExp("fehelper.*codecompress.html$", "i");
  113. for (var i = 0, len = tabs.length; i < len; i++) {
  114. if (reg.test(tabs[i].url)) {
  115. isOpened = true;
  116. tabId = tabs[i].id;
  117. break;
  118. }
  119. }
  120. if (!isOpened) {
  121. chrome.tabs.create({
  122. url: url,
  123. active: true
  124. });
  125. } else {
  126. chrome.tabs.update(tabId, {highlighted: true});
  127. }
  128. });
  129. };
  130. /**
  131. * 创建或更新成功执行的动作
  132. * @param evt
  133. * @param content
  134. * @private
  135. */
  136. var _tabUpdatedCallback = function (evt, content) {
  137. return function (newTab) {
  138. if (content) {
  139. setTimeout(function () {
  140. chrome.tabs.sendMessage(newTab.id, {
  141. type: MSG_TYPE.TAB_CREATED_OR_UPDATED,
  142. content: content,
  143. event: evt
  144. });
  145. }, 300)
  146. }
  147. };
  148. };
  149. /**
  150. * 打开对应文件,运行该Helper
  151. * @param tab
  152. * @param file
  153. * @param txt
  154. * @private
  155. */
  156. var _openFileAndRun = function (tab, file, txt) {
  157. chrome.tabs.query({windowId: chrome.windows.WINDOW_ID_CURRENT}, function (tabs) {
  158. var isOpened = false;
  159. var tabId;
  160. var reg = new RegExp("^chrome.*" + file + ".html$", "i");
  161. for (var i = 0, len = tabs.length; i < len; i++) {
  162. if (reg.test(tabs[i].url)) {
  163. isOpened = true;
  164. tabId = tabs[i].id;
  165. break;
  166. }
  167. }
  168. if (!isOpened) {
  169. chrome.tabs.create({
  170. url: 'template/fehelper_' + file + '.html',
  171. active: true
  172. }, _tabUpdatedCallback(file, txt));
  173. } else {
  174. chrome.tabs.update(tabId, {highlighted: true}, _tabUpdatedCallback(file, txt));
  175. }
  176. });
  177. };
  178. /**
  179. * 根据给定参数,运行对应的Helper
  180. */
  181. var _runHelper = function (config) {
  182. chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
  183. var tab = tabs[0];
  184. // 如果是采用独立文件方式访问,直接打开该页面即可
  185. if (config.useFile == '1') {
  186. var content = config.msgType == MSG_TYPE.QR_CODE ? tab.url : '';
  187. _openFileAndRun(tab, config.msgType, content);
  188. } else {
  189. switch (config.msgType) {
  190. //fcphelper检测
  191. case MSG_TYPE.FCP_HELPER_DETECT:
  192. _doFcpDetect(tab);
  193. break;
  194. //查看网页加载时间
  195. case MSG_TYPE.SHOW_PAGE_LOAD_TIME:
  196. _getPageWpoInfo();
  197. break;
  198. //代码压缩
  199. case MSG_TYPE.CODE_COMPRESS:
  200. _goCompressTool();
  201. break;
  202. }
  203. }
  204. });
  205. };
  206. /**
  207. * 创建扩展专属的右键菜单
  208. */
  209. var _createContextMenu = function () {
  210. _removeContextMenu();
  211. baidu.contextMenuId = chrome.contextMenus.create({
  212. title: "FeHelper",
  213. contexts: ['page', 'selection', 'editable', 'link'],
  214. documentUrlPatterns: ['http://*/*', 'https://*/*']
  215. });
  216. chrome.contextMenus.create({
  217. title: "生成二维码",
  218. contexts: ['page', 'selection', 'editable', 'link'],
  219. parentId: baidu.contextMenuId,
  220. onclick: function (info, tab) {
  221. chrome.tabs.executeScript(tab.id, {
  222. code: '(' + (function () {
  223. return window.getSelection().toString() || location.href;
  224. }).toString() + ')()',
  225. allFrames: false
  226. }, function (txt) {
  227. _openFileAndRun(tab, 'qrcode', txt);
  228. });
  229. }
  230. });
  231. chrome.contextMenus.create({
  232. type: 'separator',
  233. contexts: ['all'],
  234. parentId: baidu.contextMenuId
  235. });
  236. chrome.contextMenus.create({
  237. title: "页面取色器",
  238. contexts: ['page', 'selection', 'editable'],
  239. parentId: baidu.contextMenuId,
  240. onclick: function (info, tab) {
  241. _showColorPicker();
  242. }
  243. });
  244. chrome.contextMenus.create({
  245. type: 'separator',
  246. contexts: ['all'],
  247. parentId: baidu.contextMenuId
  248. });
  249. chrome.contextMenus.create({
  250. title: "字符串编解码",
  251. contexts: ['page', 'selection', 'editable'],
  252. parentId: baidu.contextMenuId,
  253. onclick: function (info, tab) {
  254. chrome.tabs.executeScript(tab.id, {
  255. code: '(' + (function () {
  256. return window.getSelection().toString();
  257. }).toString() + ')()',
  258. allFrames: false
  259. }, function (txt) {
  260. _openFileAndRun(tab, 'endecode', txt);
  261. });
  262. }
  263. });
  264. chrome.contextMenus.create({
  265. type: 'separator',
  266. contexts: ['all'],
  267. parentId: baidu.contextMenuId
  268. });
  269. chrome.contextMenus.create({
  270. title: "JSON格式化",
  271. contexts: ['page', 'selection', 'editable'],
  272. parentId: baidu.contextMenuId,
  273. onclick: function (info, tab) {
  274. chrome.tabs.executeScript(tab.id, {
  275. code: '(' + (function () {
  276. return window.getSelection().toString();
  277. }).toString() + ')()',
  278. allFrames: false
  279. }, function (txt) {
  280. _openFileAndRun(tab, 'jsonformat', txt);
  281. });
  282. }
  283. });
  284. chrome.contextMenus.create({
  285. type: 'separator',
  286. contexts: ['all'],
  287. parentId: baidu.contextMenuId
  288. });
  289. chrome.contextMenus.create({
  290. title: "代码格式化",
  291. contexts: ['page', 'selection', 'editable'],
  292. parentId: baidu.contextMenuId,
  293. onclick: function (info, tab) {
  294. chrome.tabs.executeScript(tab.id, {
  295. code: '(' + (function () {
  296. return window.getSelection().toString();
  297. }).toString() + ')()',
  298. allFrames: false
  299. }, function (txt) {
  300. _openFileAndRun(tab, 'codebeautify', txt);
  301. });
  302. }
  303. });
  304. };
  305. /**
  306. * 移除扩展专属的右键菜单
  307. */
  308. var _removeContextMenu = function () {
  309. if (!baidu.contextMenuId) return;
  310. chrome.contextMenus.remove(baidu.contextMenuId);
  311. baidu.contextMenuId = null;
  312. };
  313. /**
  314. * 创建或移除扩展专属的右键菜单
  315. */
  316. var _createOrRemoveContextMenu = function () {
  317. //管理右键菜单
  318. if (baidu.feOption.getOptionItem('opt_item_contextMenus') !== 'false') {
  319. _createContextMenu();
  320. } else {
  321. _removeContextMenu();
  322. }
  323. };
  324. /**
  325. * 显示color picker
  326. * @private
  327. */
  328. var _showColorPicker = function () {
  329. chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
  330. var tab = tabs[0];
  331. var tabid = tab.id;
  332. var port = chrome.tabs.connect(tabid, {name: "popupshown"});
  333. chrome.tabs.sendMessage(tabid, {enableColorPicker: true}, function (response) {
  334. chrome.tabs.sendMessage(tabid, {doPick: true}, function (r) {
  335. });
  336. });
  337. });
  338. };
  339. /**
  340. * 将网页截成一张图,实现取色
  341. * @param callback
  342. * @private
  343. */
  344. var _drawColorPicker = function (callback) {
  345. chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
  346. var tab = tabs[0];
  347. var tabid = tab.id;
  348. chrome.tabs.captureVisibleTab(null, {format: 'png'}, function (dataUrl) {
  349. chrome.tabs.sendMessage(tabid, {
  350. setPickerImage: true,
  351. pickerImage: dataUrl
  352. }, function (response) {
  353. callback && callback();
  354. });
  355. });
  356. });
  357. };
  358. /**
  359. * 接收来自content_scripts发来的消息
  360. */
  361. var _addExtensionListener = function () {
  362. chrome.runtime.onMessage.addListener(function (request, sender, callback) {
  363. //处理CSS的请求
  364. if (request.type == MSG_TYPE.GET_CSS) {
  365. //直接AJAX获取CSS文件内容
  366. baidu.network.readFileContent(request.link, callback);
  367. }
  368. //处理JS的请求
  369. else if (request.type == MSG_TYPE.GET_JS) {
  370. //直接AJAX获取JS文件内容
  371. baidu.network.readFileContent(request.link, callback);
  372. }
  373. //处理HTML的请求
  374. else if (request.type == MSG_TYPE.GET_HTML) {
  375. //直接AJAX获取JS文件内容
  376. baidu.network.readFileContent(request.link, callback);
  377. }
  378. //处理cookie
  379. else if (request.type == MSG_TYPE.GET_COOKIE) {
  380. baidu.network.getCookies(request, callback);
  381. }
  382. //移除cookie
  383. else if (request.type == MSG_TYPE.REMOVE_COOKIE) {
  384. baidu.network.removeCookie(request, callback);
  385. }
  386. //设置cookie
  387. else if (request.type == MSG_TYPE.SET_COOKIE) {
  388. baidu.network.setCookie(request, callback);
  389. }
  390. //CSS准备就绪
  391. else if (request.type == MSG_TYPE.CSS_READY) {
  392. _readyState.css = true;
  393. _detectReadyState(callback);
  394. }
  395. //JS准备就绪
  396. else if (request.type == MSG_TYPE.JS_READY) {
  397. _readyState.js = true;
  398. _detectReadyState(callback);
  399. }
  400. //HTML准备就绪
  401. else if (request.type == MSG_TYPE.HTML_READY) {
  402. _readyState.html = true;
  403. _detectReadyState(callback);
  404. }
  405. //提取配置项
  406. else if (request.type == MSG_TYPE.GET_OPTIONS) {
  407. baidu.feOption.doGetOptions(request.items, callback);
  408. }
  409. //保存配置项
  410. else if (request.type == MSG_TYPE.SET_OPTIONS) {
  411. baidu.feOption.doSetOptions(request.items, callback);
  412. //管理右键菜单
  413. _createOrRemoveContextMenu();
  414. }
  415. //保存当前网页加载时间
  416. else if (request.type == MSG_TYPE.CALC_PAGE_LOAD_TIME) {
  417. _showPageWpoInfo(request.wpo);
  418. }
  419. // 从popup中点过来的
  420. else if (request.type == MSG_TYPE.FROM_POPUP) {
  421. _runHelper(request.config);
  422. }
  423. // color picker
  424. else if (request.type == MSG_TYPE.COLOR_PICKER) {
  425. _drawColorPicker(callback);
  426. }
  427. return true;
  428. });
  429. };
  430. /**
  431. * 初始化
  432. */
  433. var _init = function () {
  434. _addExtensionListener();
  435. _createOrRemoveContextMenu();
  436. };
  437. return {
  438. init: _init,
  439. runHelper: _runHelper,
  440. showColorPicker: _showColorPicker
  441. };
  442. })();
  443. //初始化
  444. BgPageInstance.init();