mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-20 01:12:38 +01:00
d17e22a505
There were spurious error messages in the dev console of uBO in Firefox, because Firefox does not silently ignore duplicate contextual menu entries, which could occur transiently when the contextual menu entries were updated. The fix simplifies contextual menu code, and actually fulfill the original goal of avoiding to call extensions framework API as much as possible.
171 lines
7.1 KiB
JavaScript
171 lines
7.1 KiB
JavaScript
/*******************************************************************************
|
|
|
|
uBlock Origin - a browser extension to block requests.
|
|
Copyright (C) 2019-present Raymond Hill
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
|
|
Home: https://github.com/gorhill/uBlock
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
// `webext` is a promisified api of `chrome`. Entries are added as
|
|
// the promisification of uBO progress.
|
|
|
|
const webext = (( ) => { // jshint ignore:line
|
|
// >>>>> start of private scope
|
|
|
|
const promisifyNoFail = function(thisArg, fnName, outFn = r => r) {
|
|
const fn = thisArg[fnName];
|
|
return function() {
|
|
return new Promise(resolve => {
|
|
fn.call(thisArg, ...arguments, function() {
|
|
if ( chrome.runtime.lastError instanceof Object ) {
|
|
void chrome.runtime.lastError.message;
|
|
}
|
|
resolve(outFn(...arguments));
|
|
});
|
|
});
|
|
};
|
|
};
|
|
|
|
const promisify = function(thisArg, fnName) {
|
|
const fn = thisArg[fnName];
|
|
return function() {
|
|
return new Promise((resolve, reject) => {
|
|
fn.call(thisArg, ...arguments, function() {
|
|
const lastError = chrome.runtime.lastError;
|
|
if ( lastError instanceof Object ) {
|
|
return reject(lastError.message);
|
|
}
|
|
resolve(...arguments);
|
|
});
|
|
});
|
|
};
|
|
};
|
|
|
|
const webext = {
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction
|
|
browserAction: {
|
|
setBadgeBackgroundColor: promisifyNoFail(chrome.browserAction, 'setBadgeBackgroundColor'),
|
|
setBadgeText: promisifyNoFail(chrome.browserAction, 'setBadgeText'),
|
|
setIcon: promisifyNoFail(chrome.browserAction, 'setIcon'),
|
|
setTitle: promisifyNoFail(chrome.browserAction, 'setTitle'),
|
|
},
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/menus
|
|
menus: {
|
|
create: function() {
|
|
return chrome.contextMenus.create(...arguments, ( ) => {
|
|
void chrome.runtime.lastError;
|
|
});
|
|
},
|
|
onClicked: chrome.contextMenus.onClicked,
|
|
remove: promisifyNoFail(chrome.contextMenus, 'remove'),
|
|
removeAll: promisifyNoFail(chrome.contextMenus, 'removeAll'),
|
|
},
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/privacy
|
|
privacy: {
|
|
},
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage
|
|
storage: {
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local
|
|
local: {
|
|
clear: promisify(chrome.storage.local, 'clear'),
|
|
get: promisify(chrome.storage.local, 'get'),
|
|
getBytesInUse: promisify(chrome.storage.local, 'getBytesInUse'),
|
|
remove: promisify(chrome.storage.local, 'remove'),
|
|
set: promisify(chrome.storage.local, 'set'),
|
|
},
|
|
},
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs
|
|
tabs: {
|
|
get: promisifyNoFail(chrome.tabs, 'get', tab => tab instanceof Object ? tab : null),
|
|
executeScript: promisifyNoFail(chrome.tabs, 'executeScript'),
|
|
insertCSS: promisifyNoFail(chrome.tabs, 'insertCSS'),
|
|
removeCSS: promisifyNoFail(chrome.tabs, 'removeCSS'),
|
|
query: promisifyNoFail(chrome.tabs, 'query', tabs => Array.isArray(tabs) ? tabs : []),
|
|
reload: promisifyNoFail(chrome.tabs, 'reload'),
|
|
remove: promisifyNoFail(chrome.tabs, 'remove'),
|
|
update: promisifyNoFail(chrome.tabs, 'update', tab => tab instanceof Object ? tab : null),
|
|
},
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webNavigation
|
|
webNavigation: {
|
|
getFrame: promisify(chrome.webNavigation, 'getFrame'),
|
|
getAllFrames: promisify(chrome.webNavigation, 'getAllFrames'),
|
|
},
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows
|
|
windows: {
|
|
get: promisifyNoFail(chrome.windows, 'get', win => win instanceof Object ? win : null),
|
|
create: promisifyNoFail(chrome.windows, 'create', win => win instanceof Object ? win : null),
|
|
update: promisifyNoFail(chrome.windows, 'update', win => win instanceof Object ? win : null),
|
|
},
|
|
};
|
|
|
|
// browser.privacy entries
|
|
{
|
|
const settings = [
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/privacy/network
|
|
[ 'network', 'networkPredictionEnabled' ],
|
|
[ 'network', 'webRTCIPHandlingPolicy' ],
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/privacy/websites
|
|
[ 'websites', 'hyperlinkAuditingEnabled' ],
|
|
];
|
|
for ( const [ category, setting ] of settings ) {
|
|
let categoryEntry = webext.privacy[category];
|
|
if ( categoryEntry instanceof Object === false ) {
|
|
categoryEntry = webext.privacy[category] = {};
|
|
}
|
|
const settingEntry = categoryEntry[setting] = {};
|
|
const thisArg = chrome.privacy[category][setting];
|
|
settingEntry.clear = promisifyNoFail(thisArg, 'clear');
|
|
settingEntry.get = promisifyNoFail(thisArg, 'get');
|
|
settingEntry.set = promisifyNoFail(thisArg, 'set');
|
|
}
|
|
}
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/managed
|
|
if ( chrome.storage.managed instanceof Object ) {
|
|
webext.storage.managed = {
|
|
get: promisify(chrome.storage.managed, 'get'),
|
|
};
|
|
}
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/sync
|
|
if ( chrome.storage.sync instanceof Object ) {
|
|
webext.storage.sync = {
|
|
QUOTA_BYTES: chrome.storage.sync.QUOTA_BYTES,
|
|
QUOTA_BYTES_PER_ITEM: chrome.storage.sync.QUOTA_BYTES_PER_ITEM,
|
|
MAX_ITEMS: chrome.storage.sync.MAX_ITEMS,
|
|
MAX_WRITE_OPERATIONS_PER_HOUR: chrome.storage.sync.MAX_WRITE_OPERATIONS_PER_HOUR,
|
|
MAX_WRITE_OPERATIONS_PER_MINUTE: chrome.storage.sync.MAX_WRITE_OPERATIONS_PER_MINUTE,
|
|
|
|
clear: promisify(chrome.storage.sync, 'clear'),
|
|
get: promisify(chrome.storage.sync, 'get'),
|
|
getBytesInUse: promisify(chrome.storage.sync, 'getBytesInUse'),
|
|
remove: promisify(chrome.storage.sync, 'remove'),
|
|
set: promisify(chrome.storage.sync, 'set'),
|
|
};
|
|
}
|
|
|
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=608854
|
|
if ( chrome.tabs.removeCSS instanceof Function ) {
|
|
webext.tabs.removeCSS = promisifyNoFail(chrome.tabs, 'removeCSS');
|
|
}
|
|
|
|
return webext;
|
|
|
|
// <<<<< end of private scope
|
|
})();
|