You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
7.1 KiB

  1. /*******************************************************************************
  2. uBlock Origin - a browser extension to block requests.
  3. Copyright (C) 2019-present Raymond Hill
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see {http://www.gnu.org/licenses/}.
  14. Home: https://github.com/gorhill/uBlock
  15. */
  16. 'use strict';
  17. // `webext` is a promisified api of `chrome`. Entries are added as
  18. // the promisification of uBO progress.
  19. const webext = (( ) => { // jshint ignore:line
  20. // >>>>> start of private scope
  21. const noopFunc = ( ) => { };
  22. const promisifyNoFail = function(thisArg, fnName, outFn = r => r) {
  23. const fn = thisArg[fnName];
  24. return function() {
  25. return new Promise(resolve => {
  26. fn.call(thisArg, ...arguments, function() {
  27. if ( chrome.runtime.lastError instanceof Object ) {
  28. void chrome.runtime.lastError.message;
  29. }
  30. resolve(outFn(...arguments));
  31. });
  32. });
  33. };
  34. };
  35. const promisify = function(thisArg, fnName) {
  36. const fn = thisArg[fnName];
  37. return function() {
  38. return new Promise((resolve, reject) => {
  39. fn.call(thisArg, ...arguments, function() {
  40. const lastError = chrome.runtime.lastError;
  41. if ( lastError instanceof Object ) {
  42. return reject(lastError.message);
  43. }
  44. resolve(...arguments);
  45. });
  46. });
  47. };
  48. };
  49. const webext = {
  50. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction
  51. browserAction: {
  52. setBadgeBackgroundColor: promisifyNoFail(chrome.browserAction, 'setBadgeBackgroundColor'),
  53. setBadgeText: promisifyNoFail(chrome.browserAction, 'setBadgeText'),
  54. setBadgeTextColor: noopFunc,
  55. setIcon: promisifyNoFail(chrome.browserAction, 'setIcon'),
  56. setTitle: promisifyNoFail(chrome.browserAction, 'setTitle'),
  57. },
  58. cookies: {
  59. getAll: promisifyNoFail(chrome.cookies, 'getAll'),
  60. remove: promisifyNoFail(chrome.cookies, 'remove'),
  61. },
  62. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/menus
  63. /*
  64. menus: {
  65. create: function() {
  66. return chrome.contextMenus.create(...arguments, ( ) => {
  67. void chrome.runtime.lastError;
  68. });
  69. },
  70. onClicked: chrome.contextMenus.onClicked,
  71. remove: promisifyNoFail(chrome.contextMenus, 'remove'),
  72. },
  73. */
  74. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/privacy
  75. privacy: {
  76. },
  77. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage
  78. storage: {
  79. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local
  80. local: {
  81. clear: promisify(chrome.storage.local, 'clear'),
  82. get: promisify(chrome.storage.local, 'get'),
  83. getBytesInUse: promisify(chrome.storage.local, 'getBytesInUse'),
  84. remove: promisify(chrome.storage.local, 'remove'),
  85. set: promisify(chrome.storage.local, 'set'),
  86. },
  87. },
  88. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs
  89. tabs: {
  90. get: promisifyNoFail(chrome.tabs, 'get', tab => tab instanceof Object ? tab : null),
  91. executeScript: promisifyNoFail(chrome.tabs, 'executeScript'),
  92. insertCSS: promisifyNoFail(chrome.tabs, 'insertCSS'),
  93. query: promisifyNoFail(chrome.tabs, 'query', tabs => Array.isArray(tabs) ? tabs : []),
  94. reload: promisifyNoFail(chrome.tabs, 'reload'),
  95. remove: promisifyNoFail(chrome.tabs, 'remove'),
  96. update: promisifyNoFail(chrome.tabs, 'update', tab => tab instanceof Object ? tab : null),
  97. },
  98. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webNavigation
  99. webNavigation: {
  100. getFrame: promisify(chrome.webNavigation, 'getFrame'),
  101. },
  102. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows
  103. windows: {
  104. get: promisifyNoFail(chrome.windows, 'get', win => win instanceof Object ? win : null),
  105. create: promisifyNoFail(chrome.windows, 'create', win => win instanceof Object ? win : null),
  106. update: promisifyNoFail(chrome.windows, 'update', win => win instanceof Object ? win : null),
  107. },
  108. };
  109. // browser.privacy entries
  110. {
  111. const settings = [
  112. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/privacy/network
  113. [ 'network', 'networkPredictionEnabled' ],
  114. [ 'network', 'webRTCIPHandlingPolicy' ],
  115. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/privacy/websites
  116. [ 'websites', 'hyperlinkAuditingEnabled' ],
  117. ];
  118. for ( const [ category, setting ] of settings ) {
  119. let categoryEntry = webext.privacy[category];
  120. if ( categoryEntry instanceof Object === false ) {
  121. categoryEntry = webext.privacy[category] = {};
  122. }
  123. const settingEntry = categoryEntry[setting] = {};
  124. const thisArg = chrome.privacy[category][setting];
  125. settingEntry.clear = promisifyNoFail(thisArg, 'clear');
  126. settingEntry.get = promisifyNoFail(thisArg, 'get');
  127. settingEntry.set = promisifyNoFail(thisArg, 'set');
  128. }
  129. }
  130. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/managed
  131. if ( chrome.storage.managed instanceof Object ) {
  132. webext.storage.managed = {
  133. get: promisify(chrome.storage.managed, 'get'),
  134. };
  135. }
  136. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/sync
  137. if ( chrome.storage.sync instanceof Object ) {
  138. webext.storage.sync = {
  139. QUOTA_BYTES: chrome.storage.sync.QUOTA_BYTES,
  140. QUOTA_BYTES_PER_ITEM: chrome.storage.sync.QUOTA_BYTES_PER_ITEM,
  141. MAX_ITEMS: chrome.storage.sync.MAX_ITEMS,
  142. MAX_WRITE_OPERATIONS_PER_HOUR: chrome.storage.sync.MAX_WRITE_OPERATIONS_PER_HOUR,
  143. MAX_WRITE_OPERATIONS_PER_MINUTE: chrome.storage.sync.MAX_WRITE_OPERATIONS_PER_MINUTE,
  144. clear: promisify(chrome.storage.sync, 'clear'),
  145. get: promisify(chrome.storage.sync, 'get'),
  146. getBytesInUse: promisify(chrome.storage.sync, 'getBytesInUse'),
  147. remove: promisify(chrome.storage.sync, 'remove'),
  148. set: promisify(chrome.storage.sync, 'set'),
  149. };
  150. }
  151. // https://bugs.chromium.org/p/chromium/issues/detail?id=608854
  152. if ( chrome.tabs.removeCSS instanceof Function ) {
  153. webext.tabs.removeCSS = promisifyNoFail(chrome.tabs, 'removeCSS');
  154. }
  155. return webext;
  156. // <<<<< end of private scope
  157. })();