context-menus.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /* global browserCommands */// background.js
  2. /* global msg */
  3. /* global prefs */
  4. /* global CHROME FIREFOX URLS ignoreChromeError */// toolbox.js
  5. 'use strict';
  6. (() => {
  7. const contextMenus = {
  8. 'show-badge': {
  9. title: 'menuShowBadge',
  10. click: info => prefs.set(info.menuItemId, info.checked),
  11. },
  12. 'disableAll': {
  13. title: 'disableAllStyles',
  14. click: browserCommands.styleDisableAll,
  15. },
  16. 'open-manager': {
  17. title: 'openStylesManager',
  18. click: browserCommands.openManage,
  19. },
  20. 'open-options': {
  21. title: 'openOptions',
  22. click: browserCommands.openOptions,
  23. },
  24. 'reload': {
  25. presentIf: async () => (await browser.management.getSelf()).installType === 'development',
  26. title: 'reload',
  27. click: browserCommands.reload,
  28. },
  29. 'editor.contextDelete': {
  30. presentIf: () => !FIREFOX && prefs.get('editor.contextDelete'),
  31. title: 'editDeleteText',
  32. type: 'normal',
  33. contexts: ['editable'],
  34. documentUrlPatterns: [URLS.ownOrigin + 'edit*'],
  35. click: (info, tab) => {
  36. msg.sendTab(tab.id, {method: 'editDeleteText'}, undefined, 'extension')
  37. .catch(msg.ignoreError);
  38. },
  39. },
  40. };
  41. // "Delete" item in context menu for browsers that don't have it
  42. if (CHROME &&
  43. // looking at the end of UA string
  44. /(Vivaldi|Safari)\/[\d.]+$/.test(navigator.userAgent) &&
  45. // skip forks with Flash as those are likely to have the menu e.g. CentBrowser
  46. !Array.from(navigator.plugins).some(p => p.name === 'Shockwave Flash')) {
  47. prefs.__defaults['editor.contextDelete'] = true;
  48. }
  49. const keys = Object.keys(contextMenus);
  50. prefs.subscribe(keys.filter(id => typeof prefs.defaults[id] === 'boolean'),
  51. CHROME >= 62 && CHROME <= 64 ? toggleCheckmarkBugged : toggleCheckmark);
  52. prefs.subscribe(keys.filter(id => contextMenus[id].presentIf && prefs.knownKeys.includes(id)),
  53. togglePresence);
  54. createContextMenus(keys);
  55. chrome.contextMenus.onClicked.addListener((info, tab) =>
  56. contextMenus[info.menuItemId].click(info, tab));
  57. async function createContextMenus(ids) {
  58. for (const id of ids) {
  59. let item = contextMenus[id];
  60. if (item.presentIf && !await item.presentIf()) {
  61. continue;
  62. }
  63. item = Object.assign({id}, item);
  64. delete item.presentIf;
  65. item.title = chrome.i18n.getMessage(item.title);
  66. if (!item.type && typeof prefs.defaults[id] === 'boolean') {
  67. item.type = 'checkbox';
  68. item.checked = prefs.get(id);
  69. }
  70. if (!item.contexts) {
  71. item.contexts = ['browser_action'];
  72. }
  73. delete item.click;
  74. chrome.contextMenus.create(item, ignoreChromeError);
  75. }
  76. }
  77. function toggleCheckmark(id, checked) {
  78. chrome.contextMenus.update(id, {checked}, ignoreChromeError);
  79. }
  80. /** Circumvents the bug with disabling check marks in Chrome 62-64 */
  81. async function toggleCheckmarkBugged(id) {
  82. await browser.contextMenus.remove(id).catch(ignoreChromeError);
  83. createContextMenus([id]);
  84. }
  85. function togglePresence(id, checked) {
  86. if (checked) {
  87. createContextMenus([id]);
  88. } else {
  89. chrome.contextMenus.remove(id, ignoreChromeError);
  90. }
  91. }
  92. })();