vapi-messaging.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*******************************************************************************
  2. ηMatrix - a browser extension to black/white list requests.
  3. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors
  4. Copyright (C) 2019-2022 Alessio Vanni
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see {http://www.gnu.org/licenses/}.
  15. Home: https://gitlab.com/vannilla/ematrix
  16. uMatrix Home: https://github.com/gorhill/uMatrix
  17. */
  18. 'use strict';
  19. /******************************************************************************/
  20. (function () {
  21. Cu.import('chrome://ematrix/content/lib/CallbackWrapper.jsm');
  22. vAPI.messaging = {
  23. get globalMessageManager() {
  24. return Cc['@mozilla.org/globalmessagemanager;1']
  25. .getService(Ci.nsIMessageListenerManager);
  26. },
  27. frameScript: vAPI.getURL('frameScript.js'),
  28. listeners: {},
  29. defaultHandler: null,
  30. NOOPFUNC: function(){},
  31. UNHANDLED: 'vAPI.messaging.notHandled'
  32. };
  33. vAPI.messaging.listen = function (listenerName, callback) {
  34. this.listeners[listenerName] = callback;
  35. };
  36. vAPI.messaging.onMessage = function ({target, data}) {
  37. let messageManager = target.messageManager;
  38. if (!messageManager) {
  39. // Message came from a popup, and its message manager is
  40. // not usable. So instead we broadcast to the parent
  41. // window.
  42. messageManager =
  43. vAPI.browser.
  44. getOwnerWindow(target.webNavigation
  45. .QueryInterface(Ci.nsIDocShell)
  46. .chromeEventHandler).messageManager;
  47. }
  48. let channelNameRaw = data.channelName;
  49. let pos = channelNameRaw.indexOf('|');
  50. let channelName = channelNameRaw.slice(pos + 1);
  51. let callback = vAPI.messaging.NOOPFUNC;
  52. if (data.requestId !== undefined) {
  53. callback = CallbackWrapper.factory(messageManager,
  54. channelName,
  55. channelNameRaw.slice(0, pos),
  56. data.requestId).callback;
  57. }
  58. let sender = {
  59. tab: {
  60. id: vAPI.tabs.manager.tabIdFromTarget(target)
  61. }
  62. };
  63. // Specific handler
  64. let r = vAPI.messaging.UNHANDLED;
  65. let listener = vAPI.messaging.listeners[channelName];
  66. if (typeof listener === 'function') {
  67. r = listener(data.msg, sender, callback);
  68. }
  69. if (r !== vAPI.messaging.UNHANDLED) {
  70. return;
  71. }
  72. // Default handler
  73. r = vAPI.messaging.defaultHandler(data.msg, sender, callback);
  74. if (r !== vAPI.messaging.UNHANDLED) {
  75. return;
  76. }
  77. console.error('eMatrix> messaging > unknown request: %o', data);
  78. // Unhandled: Need to callback anyways in case caller expected
  79. // an answer, or else there is a memory leak on caller's side
  80. callback();
  81. };
  82. vAPI.messaging.setup = function (defaultHandler) {
  83. // Already setup?
  84. if (this.defaultHandler !== null) {
  85. return;
  86. }
  87. if (typeof defaultHandler !== 'function') {
  88. defaultHandler = function () {
  89. return vAPI.messaging.UNHANDLED;
  90. };
  91. }
  92. this.defaultHandler = defaultHandler;
  93. this.globalMessageManager.addMessageListener(location.host
  94. + ':background',
  95. this.onMessage);
  96. this.globalMessageManager.loadFrameScript(this.frameScript, true);
  97. vAPI.addCleanUpTask(function () {
  98. let gmm = vAPI.messaging.globalMessageManager;
  99. gmm.removeDelayedFrameScript(vAPI.messaging.frameScript);
  100. gmm.removeMessageListener(location.host + ':background',
  101. vAPI.messaging.onMessage);
  102. });
  103. };
  104. vAPI.messaging.broadcast = function (message) {
  105. this.globalMessageManager
  106. .broadcastAsyncMessage(location.host + ':broadcast',
  107. JSON.stringify({
  108. broadcast: true,
  109. msg: message}));
  110. };
  111. })();