mirror of https://github.com/gorhill/uBlock.git
Work toward modernizing code base: promisification
Swathes of code have been converted to use Promises/async/await. More left to do. Related commits: -915687fddb
-55cc0c6997
-e27328f931
This commit is contained in:
parent
c4ee846cd4
commit
eec53c0154
|
@ -11,6 +11,7 @@
|
||||||
"safari": false,
|
"safari": false,
|
||||||
"self": false,
|
"self": false,
|
||||||
"vAPI": false,
|
"vAPI": false,
|
||||||
|
"webext": false,
|
||||||
"µBlock": false
|
"µBlock": false
|
||||||
},
|
},
|
||||||
"laxbreak": true,
|
"laxbreak": true,
|
||||||
|
|
|
@ -43,15 +43,6 @@ vAPI.lastError = function() {
|
||||||
return chrome.runtime.lastError;
|
return chrome.runtime.lastError;
|
||||||
};
|
};
|
||||||
|
|
||||||
vAPI.apiIsPromisified = (( ) => {
|
|
||||||
try {
|
|
||||||
return browser.storage.local.get('_') instanceof Promise;
|
|
||||||
}
|
|
||||||
catch(ex) {
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
})();
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/875
|
// https://github.com/gorhill/uBlock/issues/875
|
||||||
// https://code.google.com/p/chromium/issues/detail?id=410868#c8
|
// https://code.google.com/p/chromium/issues/detail?id=410868#c8
|
||||||
// Must not leave `lastError` unchecked.
|
// Must not leave `lastError` unchecked.
|
||||||
|
@ -116,83 +107,7 @@ vAPI.app = {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
vAPI.storage = (( ) => {
|
vAPI.storage = webext.storage.local;
|
||||||
if ( vAPI.apiIsPromisified ) {
|
|
||||||
return browser.storage.local;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
clear: function(callback) {
|
|
||||||
if ( callback !== undefined ) {
|
|
||||||
return browser.storage.local.clear(...arguments);
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
browser.storage.local.clear(( ) => {
|
|
||||||
const lastError = browser.runtime.lastError;
|
|
||||||
if ( lastError instanceof Object ) {
|
|
||||||
return reject(lastError);
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
get: function(keys, callback) {
|
|
||||||
if ( callback !== undefined ) {
|
|
||||||
return browser.storage.local.get(...arguments);
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
browser.storage.local.get(keys, result => {
|
|
||||||
const lastError = browser.runtime.lastError;
|
|
||||||
if ( lastError instanceof Object ) {
|
|
||||||
return reject(lastError);
|
|
||||||
}
|
|
||||||
resolve(result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getBytesInUse: function(keys, callback) {
|
|
||||||
if ( callback !== undefined ) {
|
|
||||||
return browser.storage.local.getBytesInUse(...arguments);
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
browser.storage.local.getBytesInUse(keys, result => {
|
|
||||||
const lastError = browser.runtime.lastError;
|
|
||||||
if ( lastError instanceof Object ) {
|
|
||||||
return reject(lastError);
|
|
||||||
}
|
|
||||||
resolve(result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
remove: function(keys, callback) {
|
|
||||||
if ( callback !== undefined ) {
|
|
||||||
return browser.storage.local.remove(...arguments);
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
browser.storage.local.remove(keys, ( ) => {
|
|
||||||
const lastError = browser.runtime.lastError;
|
|
||||||
if ( lastError instanceof Object ) {
|
|
||||||
return reject(lastError);
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
set: function(items, callback) {
|
|
||||||
if ( callback !== undefined ) {
|
|
||||||
return browser.storage.local.set(...arguments);
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
browser.storage.local.set(items, ( ) => {
|
|
||||||
const lastError = browser.runtime.lastError;
|
|
||||||
if ( lastError instanceof Object ) {
|
|
||||||
return reject(lastError);
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -211,7 +126,7 @@ vAPI.storage = (( ) => {
|
||||||
// Do not mess up with existing settings if not assigning them stricter
|
// Do not mess up with existing settings if not assigning them stricter
|
||||||
// values.
|
// values.
|
||||||
|
|
||||||
vAPI.browserSettings = (function() {
|
vAPI.browserSettings = (( ) => {
|
||||||
// Not all platforms support `chrome.privacy`.
|
// Not all platforms support `chrome.privacy`.
|
||||||
if ( chrome.privacy instanceof Object === false ) { return; }
|
if ( chrome.privacy instanceof Object === false ) { return; }
|
||||||
|
|
||||||
|
@ -384,9 +299,8 @@ vAPI.isBehindTheSceneTabId = function(tabId) {
|
||||||
vAPI.unsetTabId = 0;
|
vAPI.unsetTabId = 0;
|
||||||
vAPI.noTabId = -1; // definitely not any existing tab
|
vAPI.noTabId = -1; // definitely not any existing tab
|
||||||
|
|
||||||
// To remove when tabId-as-integer has been tested enough.
|
// To ensure we always use a good tab id
|
||||||
|
const toTabId = function(tabId) {
|
||||||
const toChromiumTabId = function(tabId) {
|
|
||||||
return typeof tabId === 'number' && isNaN(tabId) === false
|
return typeof tabId === 'number' && isNaN(tabId) === false
|
||||||
? tabId
|
? tabId
|
||||||
: 0;
|
: 0;
|
||||||
|
@ -436,17 +350,12 @@ vAPI.Tabs = class {
|
||||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/151
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/151
|
||||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/680#issuecomment-515215220
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/680#issuecomment-515215220
|
||||||
if ( browser.windows instanceof Object ) {
|
if ( browser.windows instanceof Object ) {
|
||||||
browser.windows.onFocusChanged.addListener(windowId => {
|
browser.windows.onFocusChanged.addListener(async windowId => {
|
||||||
if ( windowId === browser.windows.WINDOW_ID_NONE ) { return; }
|
if ( windowId === browser.windows.WINDOW_ID_NONE ) { return; }
|
||||||
browser.tabs.query({ active: true, windowId }, tabs => {
|
const tabs = await vAPI.tabs.query({ active: true, windowId });
|
||||||
if ( Array.isArray(tabs) === false ) { return; }
|
if ( tabs.length === 0 ) { return; }
|
||||||
if ( tabs.length === 0 ) { return; }
|
const tab = tabs[0];
|
||||||
const tab = tabs[0];
|
this.onActivated({ tabId: tab.id, windowId: tab.windowId });
|
||||||
this.onActivated({
|
|
||||||
tabId: tab.id,
|
|
||||||
windowId: tab.windowId,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,32 +364,33 @@ vAPI.Tabs = class {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get(tabId, callback) {
|
async get(tabId) {
|
||||||
if ( tabId === null ) {
|
if ( tabId === null ) {
|
||||||
browser.tabs.query(
|
return this.getCurrent();
|
||||||
{ active: true, currentWindow: true },
|
|
||||||
tabs => {
|
|
||||||
void browser.runtime.lastError;
|
|
||||||
callback(
|
|
||||||
Array.isArray(tabs) && tabs.length !== 0
|
|
||||||
? tabs[0]
|
|
||||||
: null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if ( tabId <= 0 ) { return null; }
|
||||||
tabId = toChromiumTabId(tabId);
|
let tab;
|
||||||
if ( tabId === 0 ) {
|
try {
|
||||||
callback(null);
|
tab = await webext.tabs.get(tabId);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
catch(reason) {
|
||||||
|
}
|
||||||
|
return tab instanceof Object ? tab : null;
|
||||||
|
}
|
||||||
|
|
||||||
browser.tabs.get(tabId, function(tab) {
|
async getCurrent() {
|
||||||
void browser.runtime.lastError;
|
const tabs = await this.query({ active: true, currentWindow: true });
|
||||||
callback(tab);
|
return tabs.length !== 0 ? tabs[0] : null;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
async query(queryInfo) {
|
||||||
|
let tabs;
|
||||||
|
try {
|
||||||
|
tabs = await webext.tabs.query(queryInfo);
|
||||||
|
}
|
||||||
|
catch(reason) {
|
||||||
|
}
|
||||||
|
return Array.isArray(tabs) ? tabs : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Properties of the details object:
|
// Properties of the details object:
|
||||||
|
@ -491,12 +401,12 @@ vAPI.Tabs = class {
|
||||||
// foreground: undefined
|
// foreground: undefined
|
||||||
// - popup: 'popup' => open in a new window
|
// - popup: 'popup' => open in a new window
|
||||||
|
|
||||||
create(url, details) {
|
async create(url, details) {
|
||||||
if ( details.active === undefined ) {
|
if ( details.active === undefined ) {
|
||||||
details.active = true;
|
details.active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subWrapper = ( ) => {
|
const subWrapper = async ( ) => {
|
||||||
const updateDetails = {
|
const updateDetails = {
|
||||||
url: url,
|
url: url,
|
||||||
active: !!details.active
|
active: !!details.active
|
||||||
|
@ -505,8 +415,8 @@ vAPI.Tabs = class {
|
||||||
// Opening a tab from incognito window won't focus the window
|
// Opening a tab from incognito window won't focus the window
|
||||||
// in which the tab was opened
|
// in which the tab was opened
|
||||||
const focusWindow = tab => {
|
const focusWindow = tab => {
|
||||||
if ( tab.active && browser.windows instanceof Object ) {
|
if ( tab.active && vAPI.windows instanceof Object ) {
|
||||||
browser.windows.update(tab.windowId, { focused: true });
|
vAPI.windows.update(tab.windowId, { focused: true });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -519,29 +429,27 @@ vAPI.Tabs = class {
|
||||||
}
|
}
|
||||||
|
|
||||||
// update doesn't accept index, must use move
|
// update doesn't accept index, must use move
|
||||||
browser.tabs.update(
|
const tab = await vAPI.tabs.update(
|
||||||
toChromiumTabId(details.tabId),
|
toTabId(details.tabId),
|
||||||
updateDetails,
|
updateDetails
|
||||||
tab => {
|
|
||||||
// if the tab doesn't exist
|
|
||||||
if ( vAPI.lastError() ) {
|
|
||||||
browser.tabs.create(updateDetails, focusWindow);
|
|
||||||
} else if ( details.index !== undefined ) {
|
|
||||||
browser.tabs.move(tab.id, { index: details.index });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
// if the tab doesn't exist
|
||||||
|
if ( tab === null ) {
|
||||||
|
browser.tabs.create(updateDetails, focusWindow);
|
||||||
|
} else if ( details.index !== undefined ) {
|
||||||
|
browser.tabs.move(tab.id, { index: details.index });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Open in a standalone window
|
// Open in a standalone window
|
||||||
//
|
//
|
||||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/168#issuecomment-413038191
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/168#issuecomment-413038191
|
||||||
// Not all platforms support browser.windows API.
|
// Not all platforms support vAPI.windows.
|
||||||
//
|
//
|
||||||
// For some reasons, some platforms do not honor the left,top
|
// For some reasons, some platforms do not honor the left,top
|
||||||
// position when specified. I found that further calling
|
// position when specified. I found that further calling
|
||||||
// windows.update again with the same position _may_ help.
|
// windows.update again with the same position _may_ help.
|
||||||
if ( details.popup !== undefined && browser.windows instanceof Object ) {
|
if ( details.popup !== undefined && vAPI.windows instanceof Object ) {
|
||||||
const createDetails = {
|
const createDetails = {
|
||||||
url: details.url,
|
url: details.url,
|
||||||
type: details.popup,
|
type: details.popup,
|
||||||
|
@ -549,19 +457,18 @@ vAPI.Tabs = class {
|
||||||
if ( details.box instanceof Object ) {
|
if ( details.box instanceof Object ) {
|
||||||
Object.assign(createDetails, details.box);
|
Object.assign(createDetails, details.box);
|
||||||
}
|
}
|
||||||
browser.windows.create(createDetails, win => {
|
const win = await vAPI.windows.create(createDetails);
|
||||||
if ( win instanceof Object === false ) { return; }
|
if ( win === null ) { return; }
|
||||||
if ( details.box instanceof Object === false ) { return; }
|
if ( details.box instanceof Object === false ) { return; }
|
||||||
if (
|
if (
|
||||||
win.left === details.box.left &&
|
win.left === details.box.left &&
|
||||||
win.top === details.box.top
|
win.top === details.box.top
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
browser.windows.update(win.id, {
|
vAPI.windows.update(win.id, {
|
||||||
left: details.box.left,
|
left: details.box.left,
|
||||||
top: details.box.top
|
top: details.box.top
|
||||||
});
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -571,15 +478,13 @@ vAPI.Tabs = class {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vAPI.tabs.get(null, tab => {
|
const tab = await vAPI.tabs.getCurrent();
|
||||||
if ( tab ) {
|
if ( tab !== null ) {
|
||||||
details.index = tab.index + 1;
|
details.index = tab.index + 1;
|
||||||
} else {
|
} else {
|
||||||
delete details.index;
|
details.index = undefined;
|
||||||
}
|
}
|
||||||
|
subWrapper();
|
||||||
subWrapper();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Properties of the details object:
|
// Properties of the details object:
|
||||||
|
@ -593,7 +498,7 @@ vAPI.Tabs = class {
|
||||||
// it instead of opening a new one
|
// it instead of opening a new one
|
||||||
// - popup: true => open in a new window
|
// - popup: true => open in a new window
|
||||||
|
|
||||||
open(details) {
|
async open(details) {
|
||||||
let targetURL = details.url;
|
let targetURL = details.url;
|
||||||
if ( typeof targetURL !== 'string' || targetURL === '' ) {
|
if ( typeof targetURL !== 'string' || targetURL === '' ) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -628,29 +533,35 @@ vAPI.Tabs = class {
|
||||||
? targetURL
|
? targetURL
|
||||||
: targetURL.slice(0, pos);
|
: targetURL.slice(0, pos);
|
||||||
|
|
||||||
browser.tabs.query({ url: targetURLWithoutHash }, tabs => {
|
const tabs = await vAPI.tabs.query({ url: targetURLWithoutHash });
|
||||||
void browser.runtime.lastError;
|
if ( tabs.length === 0 ) {
|
||||||
const tab = Array.isArray(tabs) && tabs[0];
|
this.create(targetURL, details);
|
||||||
if ( !tab ) {
|
return;
|
||||||
this.create(targetURL, details);
|
}
|
||||||
return;
|
let tab = tabs[0];
|
||||||
}
|
const updateDetails = { active: true };
|
||||||
const updateDetails = { active: true };
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/592
|
||||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/592
|
if ( tab.url.startsWith(targetURL) === false ) {
|
||||||
if ( tab.url.startsWith(targetURL) === false ) {
|
updateDetails.url = targetURL;
|
||||||
updateDetails.url = targetURL;
|
}
|
||||||
}
|
tab = await vAPI.tabs.update(tab.id, updateDetails);
|
||||||
browser.tabs.update(tab.id, updateDetails, tab => {
|
if ( vAPI.windows instanceof Object === false ) { return; }
|
||||||
if ( browser.windows instanceof Object === false ) { return; }
|
vAPI.windows.update(tab.windowId, { focused: true });
|
||||||
browser.windows.update(tab.windowId, { focused: true });
|
}
|
||||||
});
|
|
||||||
});
|
async update() {
|
||||||
|
let tab;
|
||||||
|
try {
|
||||||
|
tab = await webext.tabs.update(...arguments);
|
||||||
|
}
|
||||||
|
catch (reason) {
|
||||||
|
}
|
||||||
|
return tab instanceof Object ? tab : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the URL of a tab. Noop if the tab does not exist.
|
// Replace the URL of a tab. Noop if the tab does not exist.
|
||||||
|
|
||||||
replace(tabId, url) {
|
replace(tabId, url) {
|
||||||
tabId = toChromiumTabId(tabId);
|
tabId = toTabId(tabId);
|
||||||
if ( tabId === 0 ) { return; }
|
if ( tabId === 0 ) { return; }
|
||||||
|
|
||||||
let targetURL = url;
|
let targetURL = url;
|
||||||
|
@ -660,18 +571,17 @@ vAPI.Tabs = class {
|
||||||
targetURL = vAPI.getURL(targetURL);
|
targetURL = vAPI.getURL(targetURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
browser.tabs.update(tabId, { url: targetURL }, vAPI.resetLastError);
|
vAPI.tabs.update(tabId, { url: targetURL });
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(tabId) {
|
remove(tabId) {
|
||||||
tabId = toChromiumTabId(tabId);
|
tabId = toTabId(tabId);
|
||||||
if ( tabId === 0 ) { return; }
|
if ( tabId === 0 ) { return; }
|
||||||
|
|
||||||
browser.tabs.remove(tabId, vAPI.resetLastError);
|
browser.tabs.remove(tabId, vAPI.resetLastError);
|
||||||
}
|
}
|
||||||
|
|
||||||
reload(tabId, bypassCache = false) {
|
reload(tabId, bypassCache = false) {
|
||||||
tabId = toChromiumTabId(tabId);
|
tabId = toTabId(tabId);
|
||||||
if ( tabId === 0 ) { return; }
|
if ( tabId === 0 ) { return; }
|
||||||
|
|
||||||
browser.tabs.reload(
|
browser.tabs.reload(
|
||||||
|
@ -681,16 +591,13 @@ vAPI.Tabs = class {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
select(tabId) {
|
async select(tabId) {
|
||||||
tabId = toChromiumTabId(tabId);
|
tabId = toTabId(tabId);
|
||||||
if ( tabId === 0 ) { return; }
|
if ( tabId === 0 ) { return; }
|
||||||
|
const tab = await vAPI.tabs.update(tabId, { active: true });
|
||||||
browser.tabs.update(tabId, { active: true }, function(tab) {
|
if ( tab === null ) { return; }
|
||||||
void browser.runtime.lastError;
|
if ( vAPI.windows instanceof Object === false ) { return; }
|
||||||
if ( !tab ) { return; }
|
vAPI.windows.update(tab.windowId, { focused: true });
|
||||||
if ( browser.windows instanceof Object === false ) { return; }
|
|
||||||
browser.windows.update(tab.windowId, { focused: true });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
injectScript(tabId, details, callback) {
|
injectScript(tabId, details, callback) {
|
||||||
|
@ -703,7 +610,7 @@ vAPI.Tabs = class {
|
||||||
};
|
};
|
||||||
if ( tabId ) {
|
if ( tabId ) {
|
||||||
browser.tabs.executeScript(
|
browser.tabs.executeScript(
|
||||||
toChromiumTabId(tabId),
|
toTabId(tabId),
|
||||||
details,
|
details,
|
||||||
onScriptExecuted
|
onScriptExecuted
|
||||||
);
|
);
|
||||||
|
@ -749,6 +656,41 @@ vAPI.Tabs = class {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
if ( browser.windows instanceof Object ) {
|
||||||
|
vAPI.windows = {
|
||||||
|
get: async function() {
|
||||||
|
let win;
|
||||||
|
try {
|
||||||
|
win = await webext.windows.get(...arguments);
|
||||||
|
}
|
||||||
|
catch (reason) {
|
||||||
|
}
|
||||||
|
return win instanceof Object ? win : null;
|
||||||
|
},
|
||||||
|
create: async function() {
|
||||||
|
let win;
|
||||||
|
try {
|
||||||
|
win = await webext.windows.create(...arguments);
|
||||||
|
}
|
||||||
|
catch (reason) {
|
||||||
|
}
|
||||||
|
return win instanceof Object ? win : null;
|
||||||
|
},
|
||||||
|
update: async function() {
|
||||||
|
let win;
|
||||||
|
try {
|
||||||
|
win = await webext.windows.update(...arguments);
|
||||||
|
}
|
||||||
|
catch (reason) {
|
||||||
|
}
|
||||||
|
return win instanceof Object ? win : null;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
// Must read: https://code.google.com/p/chromium/issues/detail?id=410868#c8
|
// Must read: https://code.google.com/p/chromium/issues/detail?id=410868#c8
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/19
|
// https://github.com/chrisaljoudi/uBlock/issues/19
|
||||||
|
@ -852,8 +794,17 @@ vAPI.setIcon = (( ) => {
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const onTabReady = function(tab, details) {
|
// parts: bit 0 = icon
|
||||||
if ( vAPI.lastError() || !tab ) { return; }
|
// bit 1 = badge text
|
||||||
|
// bit 2 = badge color
|
||||||
|
// bit 3 = hide badge
|
||||||
|
|
||||||
|
return async function(tabId, details) {
|
||||||
|
tabId = toTabId(tabId);
|
||||||
|
if ( tabId === 0 ) { return; }
|
||||||
|
|
||||||
|
const tab = await vAPI.tabs.get(tabId);
|
||||||
|
if ( tab === null ) { return; }
|
||||||
|
|
||||||
const { parts, state, badge, color } = details;
|
const { parts, state, badge, color } = details;
|
||||||
|
|
||||||
|
@ -883,18 +834,6 @@ vAPI.setIcon = (( ) => {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// parts: bit 0 = icon
|
|
||||||
// bit 1 = badge text
|
|
||||||
// bit 2 = badge color
|
|
||||||
// bit 3 = hide badge
|
|
||||||
|
|
||||||
return function(tabId, details) {
|
|
||||||
tabId = toChromiumTabId(tabId);
|
|
||||||
if ( tabId === 0 ) { return; }
|
|
||||||
|
|
||||||
browser.tabs.get(tabId, tab => onTabReady(tab, details));
|
|
||||||
|
|
||||||
if ( vAPI.contextMenu instanceof Object ) {
|
if ( vAPI.contextMenu instanceof Object ) {
|
||||||
vAPI.contextMenu.onMustUpdate(tabId);
|
vAPI.contextMenu.onMustUpdate(tabId);
|
||||||
|
@ -1381,48 +1320,27 @@ vAPI.commands = chrome.commands;
|
||||||
// Also, UC Browser: http://www.upsieutoc.com/image/WXuH
|
// Also, UC Browser: http://www.upsieutoc.com/image/WXuH
|
||||||
|
|
||||||
vAPI.adminStorage = (( ) => {
|
vAPI.adminStorage = (( ) => {
|
||||||
if ( browser.storage.managed instanceof Object === false ) {
|
if ( webext.storage.managed instanceof Object === false ) {
|
||||||
return {
|
return {
|
||||||
getItem: function() {
|
getItem: function() {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const managedStorage = vAPI.apiIsPromisified
|
|
||||||
? browser.storage.managed
|
|
||||||
: {
|
|
||||||
get: function(keys) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
browser.storage.managed.get(keys, result => {
|
|
||||||
const lastError = browser.runtime.lastError;
|
|
||||||
if ( lastError instanceof Object ) {
|
|
||||||
return reject(lastError);
|
|
||||||
}
|
|
||||||
resolve(result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return {
|
return {
|
||||||
getItem: async function(key) {
|
getItem: async function(key) {
|
||||||
let bin;
|
let bin;
|
||||||
try {
|
try {
|
||||||
bin = await managedStorage.get(key);
|
bin = await webext.storage.managed.get(key);
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
}
|
}
|
||||||
let data;
|
if ( bin instanceof Object ) {
|
||||||
if (
|
return bin[key];
|
||||||
chrome.runtime.lastError instanceof Object === false &&
|
|
||||||
bin instanceof Object
|
|
||||||
) {
|
|
||||||
data = bin[key];
|
|
||||||
}
|
}
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
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
|
||||||
|
storage: {
|
||||||
|
local: {
|
||||||
|
clear: function() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.storage.local.clear(( ) => {
|
||||||
|
const lastError = chrome.runtime.lastError;
|
||||||
|
if ( lastError instanceof Object ) {
|
||||||
|
return reject(lastError);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
get: function() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.storage.local.get(...arguments, result => {
|
||||||
|
const lastError = chrome.runtime.lastError;
|
||||||
|
if ( lastError instanceof Object ) {
|
||||||
|
return reject(lastError);
|
||||||
|
}
|
||||||
|
resolve(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getBytesInUse: function() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.storage.local.getBytesInUse(...arguments, result => {
|
||||||
|
const lastError = chrome.runtime.lastError;
|
||||||
|
if ( lastError instanceof Object ) {
|
||||||
|
return reject(lastError);
|
||||||
|
}
|
||||||
|
resolve(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
remove: function() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.storage.local.remove(...arguments, ( ) => {
|
||||||
|
const lastError = chrome.runtime.lastError;
|
||||||
|
if ( lastError instanceof Object ) {
|
||||||
|
return reject(lastError);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
set: function() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.storage.local.set(...arguments, ( ) => {
|
||||||
|
const lastError = chrome.runtime.lastError;
|
||||||
|
if ( lastError instanceof Object ) {
|
||||||
|
return reject(lastError);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
tabs: {
|
||||||
|
get: function() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
chrome.tabs.get(...arguments, tab => {
|
||||||
|
void chrome.runtime.lastError;
|
||||||
|
resolve(tab instanceof Object ? tab : null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
query: function() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
chrome.tabs.query(...arguments, tabs => {
|
||||||
|
void chrome.runtime.lastError;
|
||||||
|
resolve(Array.isArray(tabs) ? tabs : []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
update: function() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
chrome.tabs.update(...arguments, tab => {
|
||||||
|
void chrome.runtime.lastError;
|
||||||
|
resolve(tab instanceof Object ? tab : null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
windows: {
|
||||||
|
get: async function() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
chrome.windows.get(...arguments, win => {
|
||||||
|
void chrome.runtime.lastError;
|
||||||
|
resolve(win instanceof Object ? win : null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
create: async function() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
chrome.windows.create(...arguments, win => {
|
||||||
|
void chrome.runtime.lastError;
|
||||||
|
resolve(win instanceof Object ? win : null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
update: async function() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
chrome.windows.update(...arguments, win => {
|
||||||
|
void chrome.runtime.lastError;
|
||||||
|
resolve(win instanceof Object ? win : null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( chrome.storage.managed instanceof Object ) {
|
||||||
|
webext.storage.managed = {
|
||||||
|
get: function() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.storage.local.get(...arguments, result => {
|
||||||
|
const lastError = chrome.runtime.lastError;
|
||||||
|
if ( lastError instanceof Object ) {
|
||||||
|
return reject(lastError);
|
||||||
|
}
|
||||||
|
resolve(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
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';
|
||||||
|
|
||||||
|
const webext = browser; // jshint ignore:line
|
|
@ -9,6 +9,7 @@
|
||||||
<script src="lib/lz4/lz4-block-codec-any.js"></script>
|
<script src="lib/lz4/lz4-block-codec-any.js"></script>
|
||||||
<script src="lib/punycode.js"></script>
|
<script src="lib/punycode.js"></script>
|
||||||
<script src="lib/publicsuffixlist/publicsuffixlist.js"></script>
|
<script src="lib/publicsuffixlist/publicsuffixlist.js"></script>
|
||||||
|
<script src="js/webext.js"></script>
|
||||||
<script src="js/vapi.js"></script>
|
<script src="js/vapi.js"></script>
|
||||||
<script src="js/vapi-common.js"></script>
|
<script src="js/vapi-common.js"></script>
|
||||||
<script src="js/vapi-background.js"></script>
|
<script src="js/vapi-background.js"></script>
|
||||||
|
|
|
@ -54,64 +54,15 @@
|
||||||
|
|
||||||
const STORAGE_NAME = 'uBlock0CacheStorage';
|
const STORAGE_NAME = 'uBlock0CacheStorage';
|
||||||
|
|
||||||
// Default to webext storage. Wrapped into promises if the API does not
|
// Default to webext storage.
|
||||||
// support returning promises.
|
const localStorage = webext.storage.local;
|
||||||
const promisified = (( ) => {
|
|
||||||
try {
|
|
||||||
return browser.storage.local.get('_') instanceof Promise;
|
|
||||||
}
|
|
||||||
catch(ex) {
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
})();
|
|
||||||
|
|
||||||
const api = {
|
const api = {
|
||||||
name: 'browser.storage.local',
|
name: 'browser.storage.local',
|
||||||
get: promisified ?
|
get: localStorage.get,
|
||||||
browser.storage.local.get :
|
set: localStorage.set,
|
||||||
function(keys) {
|
remove: localStorage.remove,
|
||||||
return new Promise(resolve => {
|
clear: localStorage.clear,
|
||||||
browser.storage.local.get(keys, bin => {
|
getBytesInUse: localStorage.getBytesInUse,
|
||||||
resolve(bin);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
set: promisified ?
|
|
||||||
browser.storage.local.set :
|
|
||||||
function(keys) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
browser.storage.local.set(keys, ( ) => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
remove: promisified ?
|
|
||||||
browser.storage.local.remove :
|
|
||||||
function(keys) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
browser.storage.local.remove(keys, ( ) => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
clear: promisified ?
|
|
||||||
browser.storage.local.clear :
|
|
||||||
function() {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
browser.storage.local.clear(( ) => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getBytesInUse: promisified ?
|
|
||||||
browser.storage.local.getBytesInUse :
|
|
||||||
function(keys) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
browser.storage.local.getBytesInUse(keys, count => {
|
|
||||||
resolve(count);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
select: function(selectedBackend) {
|
select: function(selectedBackend) {
|
||||||
let actualBackend = selectedBackend;
|
let actualBackend = selectedBackend;
|
||||||
if ( actualBackend === undefined || actualBackend === 'unset' ) {
|
if ( actualBackend === undefined || actualBackend === 'unset' ) {
|
||||||
|
@ -139,7 +90,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reassign API entries to that of indexedDB-based ones
|
// Reassign API entries to that of indexedDB-based ones
|
||||||
const selectIDB = function() {
|
const selectIDB = async function() {
|
||||||
let db;
|
let db;
|
||||||
let dbPromise;
|
let dbPromise;
|
||||||
let dbTimer;
|
let dbTimer;
|
||||||
|
@ -244,7 +195,7 @@
|
||||||
return dbPromise;
|
return dbPromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFromDb = function(keys, keyvalStore, callback) {
|
const getFromDb = async function(keys, keyvalStore, callback) {
|
||||||
if ( typeof callback !== 'function' ) { return; }
|
if ( typeof callback !== 'function' ) { return; }
|
||||||
if ( keys.length === 0 ) { return callback(keyvalStore); }
|
if ( keys.length === 0 ) { return callback(keyvalStore); }
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
@ -261,7 +212,8 @@
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
getDb().then(db => {
|
try {
|
||||||
|
const db = await getDb();
|
||||||
if ( !db ) { return callback(); }
|
if ( !db ) { return callback(); }
|
||||||
const transaction = db.transaction(STORAGE_NAME, 'readonly');
|
const transaction = db.transaction(STORAGE_NAME, 'readonly');
|
||||||
transaction.oncomplete =
|
transaction.oncomplete =
|
||||||
|
@ -277,29 +229,29 @@
|
||||||
req.onsuccess = gotOne;
|
req.onsuccess = gotOne;
|
||||||
req.onerror = noopfn;
|
req.onerror = noopfn;
|
||||||
}
|
}
|
||||||
}).catch(reason => {
|
}
|
||||||
|
catch(reason) {
|
||||||
console.info(`cacheStorage.getFromDb() failed: ${reason}`);
|
console.info(`cacheStorage.getFromDb() failed: ${reason}`);
|
||||||
callback();
|
callback();
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const visitAllFromDb = function(visitFn) {
|
const visitAllFromDb = async function(visitFn) {
|
||||||
getDb().then(db => {
|
const db = await getDb();
|
||||||
if ( !db ) { return visitFn(); }
|
if ( !db ) { return visitFn(); }
|
||||||
const transaction = db.transaction(STORAGE_NAME, 'readonly');
|
const transaction = db.transaction(STORAGE_NAME, 'readonly');
|
||||||
transaction.oncomplete =
|
transaction.oncomplete =
|
||||||
transaction.onerror =
|
transaction.onerror =
|
||||||
transaction.onabort = ( ) => visitFn();
|
transaction.onabort = ( ) => visitFn();
|
||||||
const table = transaction.objectStore(STORAGE_NAME);
|
const table = transaction.objectStore(STORAGE_NAME);
|
||||||
const req = table.openCursor();
|
const req = table.openCursor();
|
||||||
req.onsuccess = function(ev) {
|
req.onsuccess = function(ev) {
|
||||||
let cursor = ev.target && ev.target.result;
|
let cursor = ev.target && ev.target.result;
|
||||||
if ( !cursor ) { return; }
|
if ( !cursor ) { return; }
|
||||||
let entry = cursor.value;
|
let entry = cursor.value;
|
||||||
visitFn(entry);
|
visitFn(entry);
|
||||||
cursor.continue();
|
cursor.continue();
|
||||||
};
|
};
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAllFromDb = function(callback) {
|
const getAllFromDb = function(callback) {
|
||||||
|
@ -335,7 +287,7 @@
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/transaction
|
// https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/transaction
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/put
|
// https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/put
|
||||||
|
|
||||||
const putToDb = function(keyvalStore, callback) {
|
const putToDb = async function(keyvalStore, callback) {
|
||||||
if ( typeof callback !== 'function' ) {
|
if ( typeof callback !== 'function' ) {
|
||||||
callback = noopfn;
|
callback = noopfn;
|
||||||
}
|
}
|
||||||
|
@ -359,67 +311,67 @@
|
||||||
µBlock.lz4Codec.encode(key, data).then(handleEncodingResult)
|
µBlock.lz4Codec.encode(key, data).then(handleEncodingResult)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Promise.all(promises).then(results => {
|
const finish = ( ) => {
|
||||||
|
if ( callback === undefined ) { return; }
|
||||||
|
let cb = callback;
|
||||||
|
callback = undefined;
|
||||||
|
cb();
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const results = await Promise.all(promises);
|
||||||
const db = results[0];
|
const db = results[0];
|
||||||
if ( !db ) { return callback(); }
|
if ( !db ) { return callback(); }
|
||||||
const finish = ( ) => {
|
const transaction = db.transaction(
|
||||||
if ( callback === undefined ) { return; }
|
STORAGE_NAME,
|
||||||
let cb = callback;
|
'readwrite'
|
||||||
callback = undefined;
|
);
|
||||||
cb();
|
transaction.oncomplete =
|
||||||
};
|
transaction.onerror =
|
||||||
try {
|
transaction.onabort = finish;
|
||||||
const transaction = db.transaction(
|
const table = transaction.objectStore(STORAGE_NAME);
|
||||||
STORAGE_NAME,
|
for ( const entry of entries ) {
|
||||||
'readwrite'
|
table.put(entry);
|
||||||
);
|
|
||||||
transaction.oncomplete =
|
|
||||||
transaction.onerror =
|
|
||||||
transaction.onabort = finish;
|
|
||||||
const table = transaction.objectStore(STORAGE_NAME);
|
|
||||||
for ( const entry of entries ) {
|
|
||||||
table.put(entry);
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
finish();
|
|
||||||
}
|
}
|
||||||
});
|
} catch (ex) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteFromDb = function(input, callback) {
|
const deleteFromDb = async function(input, callback) {
|
||||||
if ( typeof callback !== 'function' ) {
|
if ( typeof callback !== 'function' ) {
|
||||||
callback = noopfn;
|
callback = noopfn;
|
||||||
}
|
}
|
||||||
const keys = Array.isArray(input) ? input.slice() : [ input ];
|
const keys = Array.isArray(input) ? input.slice() : [ input ];
|
||||||
if ( keys.length === 0 ) { return callback(); }
|
if ( keys.length === 0 ) { return callback(); }
|
||||||
getDb().then(db => {
|
const finish = ( ) => {
|
||||||
|
if ( callback === undefined ) { return; }
|
||||||
|
let cb = callback;
|
||||||
|
callback = undefined;
|
||||||
|
cb();
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const db = await getDb();
|
||||||
if ( !db ) { return callback(); }
|
if ( !db ) { return callback(); }
|
||||||
const finish = ( ) => {
|
const transaction = db.transaction(STORAGE_NAME, 'readwrite');
|
||||||
if ( callback === undefined ) { return; }
|
transaction.oncomplete =
|
||||||
let cb = callback;
|
transaction.onerror =
|
||||||
callback = undefined;
|
transaction.onabort = finish;
|
||||||
cb();
|
const table = transaction.objectStore(STORAGE_NAME);
|
||||||
};
|
for ( const key of keys ) {
|
||||||
try {
|
table.delete(key);
|
||||||
const transaction = db.transaction(STORAGE_NAME, 'readwrite');
|
|
||||||
transaction.oncomplete =
|
|
||||||
transaction.onerror =
|
|
||||||
transaction.onabort = finish;
|
|
||||||
const table = transaction.objectStore(STORAGE_NAME);
|
|
||||||
for ( const key of keys ) {
|
|
||||||
table.delete(key);
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
finish();
|
|
||||||
}
|
}
|
||||||
});
|
} catch (ex) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const clearDb = function(callback) {
|
const clearDb = async function(callback) {
|
||||||
if ( typeof callback !== 'function' ) {
|
if ( typeof callback !== 'function' ) {
|
||||||
callback = noopfn;
|
callback = noopfn;
|
||||||
}
|
}
|
||||||
getDb().then(db => {
|
try {
|
||||||
|
const db = await getDb();
|
||||||
|
if ( !db ) { return callback(); }
|
||||||
const transaction = db.transaction(STORAGE_NAME, 'readwrite');
|
const transaction = db.transaction(STORAGE_NAME, 'readwrite');
|
||||||
transaction.oncomplete =
|
transaction.oncomplete =
|
||||||
transaction.onerror =
|
transaction.onerror =
|
||||||
|
@ -427,77 +379,77 @@
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
transaction.objectStore(STORAGE_NAME).clear();
|
transaction.objectStore(STORAGE_NAME).clear();
|
||||||
}).catch(reason => {
|
}
|
||||||
|
catch(reason) {
|
||||||
console.info(`cacheStorage.clearDb() failed: ${reason}`);
|
console.info(`cacheStorage.clearDb() failed: ${reason}`);
|
||||||
callback();
|
callback();
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return getDb().then(db => {
|
await getDb();
|
||||||
if ( !db ) { return false; }
|
if ( !db ) { return false; }
|
||||||
api.name = 'indexedDB';
|
|
||||||
api.get = function get(keys) {
|
api.name = 'indexedDB';
|
||||||
return new Promise(resolve => {
|
api.get = function get(keys) {
|
||||||
if ( keys === null ) {
|
return new Promise(resolve => {
|
||||||
return getAllFromDb(bin => resolve(bin));
|
if ( keys === null ) {
|
||||||
}
|
return getAllFromDb(bin => resolve(bin));
|
||||||
let toRead, output = {};
|
}
|
||||||
if ( typeof keys === 'string' ) {
|
let toRead, output = {};
|
||||||
toRead = [ keys ];
|
if ( typeof keys === 'string' ) {
|
||||||
} else if ( Array.isArray(keys) ) {
|
toRead = [ keys ];
|
||||||
toRead = keys;
|
} else if ( Array.isArray(keys) ) {
|
||||||
} else /* if ( typeof keys === 'object' ) */ {
|
toRead = keys;
|
||||||
toRead = Object.keys(keys);
|
} else /* if ( typeof keys === 'object' ) */ {
|
||||||
output = keys;
|
toRead = Object.keys(keys);
|
||||||
}
|
output = keys;
|
||||||
getFromDb(toRead, output, bin => resolve(bin));
|
}
|
||||||
});
|
getFromDb(toRead, output, bin => resolve(bin));
|
||||||
};
|
});
|
||||||
api.set = function set(keys) {
|
};
|
||||||
return new Promise(resolve => {
|
api.set = function set(keys) {
|
||||||
putToDb(keys, details => resolve(details));
|
return new Promise(resolve => {
|
||||||
});
|
putToDb(keys, details => resolve(details));
|
||||||
};
|
});
|
||||||
api.remove = function remove(keys) {
|
};
|
||||||
return new Promise(resolve => {
|
api.remove = function remove(keys) {
|
||||||
deleteFromDb(keys, ( ) => resolve());
|
return new Promise(resolve => {
|
||||||
});
|
deleteFromDb(keys, ( ) => resolve());
|
||||||
};
|
});
|
||||||
api.clear = function clear() {
|
};
|
||||||
return new Promise(resolve => {
|
api.clear = function clear() {
|
||||||
clearDb(( ) => resolve());
|
return new Promise(resolve => {
|
||||||
});
|
clearDb(( ) => resolve());
|
||||||
};
|
});
|
||||||
api.getBytesInUse = function getBytesInUse() {
|
};
|
||||||
return Promise.resolve(0);
|
api.getBytesInUse = function getBytesInUse() {
|
||||||
};
|
return Promise.resolve(0);
|
||||||
return true;
|
};
|
||||||
});
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/328
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/328
|
||||||
// Delete cache-related entries from webext storage.
|
// Delete cache-related entries from webext storage.
|
||||||
const clearWebext = function() {
|
const clearWebext = async function() {
|
||||||
browser.storage.local.get('assetCacheRegistry', bin => {
|
const bin = await webext.storage.local.get('assetCacheRegistry');
|
||||||
if (
|
if (
|
||||||
bin instanceof Object === false ||
|
bin instanceof Object === false ||
|
||||||
bin.assetCacheRegistry instanceof Object === false
|
bin.assetCacheRegistry instanceof Object === false
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
const toRemove = [
|
||||||
|
'assetCacheRegistry',
|
||||||
|
'assetSourceRegistry',
|
||||||
|
'resourcesSelfie',
|
||||||
|
'selfie'
|
||||||
|
];
|
||||||
|
for ( const key in bin.assetCacheRegistry ) {
|
||||||
|
if ( bin.assetCacheRegistry.hasOwnProperty(key) ) {
|
||||||
|
toRemove.push('cache/' + key);
|
||||||
}
|
}
|
||||||
const toRemove = [
|
}
|
||||||
'assetCacheRegistry',
|
webext.storage.local.remove(toRemove);
|
||||||
'assetSourceRegistry',
|
|
||||||
'resourcesSelfie',
|
|
||||||
'selfie'
|
|
||||||
];
|
|
||||||
for ( const key in bin.assetCacheRegistry ) {
|
|
||||||
if ( bin.assetCacheRegistry.hasOwnProperty(key) ) {
|
|
||||||
toRemove.push('cache/' + key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
browser.storage.local.remove(toRemove);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const clearIDB = function() {
|
const clearIDB = function() {
|
||||||
|
|
|
@ -128,36 +128,37 @@ const relaxBlockingMode = (( ) => {
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
vAPI.commands.onCommand.addListener(command => {
|
vAPI.commands.onCommand.addListener(async command => {
|
||||||
const µb = µBlock;
|
const µb = µBlock;
|
||||||
|
|
||||||
switch ( command ) {
|
switch ( command ) {
|
||||||
case 'launch-element-picker':
|
case 'launch-element-picker':
|
||||||
case 'launch-element-zapper':
|
case 'launch-element-zapper': {
|
||||||
vAPI.tabs.get(null, tab => {
|
const tab = await vAPI.tabs.getCurrent();
|
||||||
if ( tab instanceof Object === false ) { return; }
|
if ( tab instanceof Object === false ) { return; }
|
||||||
µb.mouseEventRegister.x = µb.mouseEventRegister.y = -1;
|
µb.mouseEventRegister.x = µb.mouseEventRegister.y = -1;
|
||||||
µb.elementPickerExec(
|
µb.elementPickerExec(
|
||||||
tab.id,
|
tab.id,
|
||||||
undefined,
|
undefined,
|
||||||
command === 'launch-element-zapper'
|
command === 'launch-element-zapper'
|
||||||
);
|
);
|
||||||
});
|
break;
|
||||||
break;
|
}
|
||||||
case 'launch-logger':
|
case 'launch-logger': {
|
||||||
vAPI.tabs.get(null, tab => {
|
const tab = await vAPI.tabs.getCurrent();
|
||||||
const hash = tab.url.startsWith(vAPI.getURL(''))
|
if ( tab instanceof Object === false ) { return; }
|
||||||
? ''
|
const hash = tab.url.startsWith(vAPI.getURL(''))
|
||||||
: `#_+${tab.id}`;
|
? ''
|
||||||
µb.openNewTab({
|
: `#_+${tab.id}`;
|
||||||
url: `logger-ui.html${hash}`,
|
µb.openNewTab({
|
||||||
select: true,
|
url: `logger-ui.html${hash}`,
|
||||||
index: -1
|
select: true,
|
||||||
});
|
index: -1
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 'relax-blocking-mode':
|
case 'relax-blocking-mode':
|
||||||
vAPI.tabs.get(null, relaxBlockingMode);
|
relaxBlockingMode(await vAPI.tabs.getCurrent());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -128,17 +128,16 @@ const update = function(tabId = undefined) {
|
||||||
// For unknown reasons, the currently active tab will not be successfully
|
// For unknown reasons, the currently active tab will not be successfully
|
||||||
// looked up after closing a window.
|
// looked up after closing a window.
|
||||||
|
|
||||||
vAPI.contextMenu.onMustUpdate = function(tabId = undefined) {
|
vAPI.contextMenu.onMustUpdate = async function(tabId = undefined) {
|
||||||
if ( µBlock.userSettings.contextMenuEnabled === false ) {
|
if ( µBlock.userSettings.contextMenuEnabled === false ) {
|
||||||
return update();
|
return update();
|
||||||
}
|
}
|
||||||
if ( tabId !== undefined ) {
|
if ( tabId !== undefined ) {
|
||||||
return update(tabId);
|
return update(tabId);
|
||||||
}
|
}
|
||||||
vAPI.tabs.get(null, tab => {
|
const tab = await vAPI.tabs.getCurrent();
|
||||||
if ( tab instanceof Object === false ) { return; }
|
if ( tab instanceof Object === false ) { return; }
|
||||||
update(tab.id);
|
update(tab.id);
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return { update: vAPI.contextMenu.onMustUpdate };
|
return { update: vAPI.contextMenu.onMustUpdate };
|
||||||
|
|
|
@ -346,22 +346,20 @@ const popupDataFromTabId = function(tabId, tabTitle) {
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
const popupDataFromRequest = function(request, callback) {
|
const popupDataFromRequest = async function(request) {
|
||||||
if ( request.tabId ) {
|
if ( request.tabId ) {
|
||||||
callback(popupDataFromTabId(request.tabId, ''));
|
return popupDataFromTabId(request.tabId, '');
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Still no target tab id? Use currently selected tab.
|
// Still no target tab id? Use currently selected tab.
|
||||||
vAPI.tabs.get(null, function(tab) {
|
const tab = await vAPI.tabs.getCurrent();
|
||||||
var tabId = '';
|
let tabId = '';
|
||||||
var tabTitle = '';
|
let tabTitle = '';
|
||||||
if ( tab ) {
|
if ( tab instanceof Object ) {
|
||||||
tabId = tab.id;
|
tabId = tab.id;
|
||||||
tabTitle = tab.title || '';
|
tabTitle = tab.title || '';
|
||||||
}
|
}
|
||||||
callback(popupDataFromTabId(tabId, tabTitle));
|
return popupDataFromTabId(tabId, tabTitle);
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMessage = function(request, sender, callback) {
|
const onMessage = function(request, sender, callback) {
|
||||||
|
@ -370,7 +368,9 @@ const onMessage = function(request, sender, callback) {
|
||||||
// Async
|
// Async
|
||||||
switch ( request.what ) {
|
switch ( request.what ) {
|
||||||
case 'getPopupData':
|
case 'getPopupData':
|
||||||
popupDataFromRequest(request, callback);
|
popupDataFromRequest(request).then(popupData => {
|
||||||
|
callback(popupData);
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1151,7 +1151,7 @@ vAPI.messaging.listen({
|
||||||
const µb = µBlock;
|
const µb = µBlock;
|
||||||
const extensionOriginURL = vAPI.getURL('');
|
const extensionOriginURL = vAPI.getURL('');
|
||||||
|
|
||||||
const getLoggerData = function(details, activeTabId, callback) {
|
const getLoggerData = async function(details, activeTabId, callback) {
|
||||||
const response = {
|
const response = {
|
||||||
colorBlind: µb.userSettings.colorBlindFriendly,
|
colorBlind: µb.userSettings.colorBlindFriendly,
|
||||||
entries: µb.logger.readAll(details.ownerId),
|
entries: µb.logger.readAll(details.ownerId),
|
||||||
|
@ -1178,26 +1178,20 @@ const getLoggerData = function(details, activeTabId, callback) {
|
||||||
response.activeTabId = undefined;
|
response.activeTabId = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( details.popupLoggerBoxChanged && browser.windows instanceof Object ) {
|
if ( details.popupLoggerBoxChanged && vAPI.windows instanceof Object ) {
|
||||||
browser.tabs.query(
|
const tabs = await vAPI.tabs.query({
|
||||||
{ url: vAPI.getURL('/logger-ui.html?popup=1') },
|
url: vAPI.getURL('/logger-ui.html?popup=1')
|
||||||
tabs => {
|
});
|
||||||
if ( Array.isArray(tabs) === false ) { return; }
|
if ( tabs.length !== 0 ) {
|
||||||
if ( tabs.length === 0 ) { return; }
|
const win = await vAPI.windows.get(tabs[0].windowId);
|
||||||
browser.windows.get(tabs[0].windowId, win => {
|
if ( win === null ) { return; }
|
||||||
if ( win instanceof Object === false ) { return; }
|
vAPI.localStorage.setItem('popupLoggerBox', JSON.stringify({
|
||||||
vAPI.localStorage.setItem(
|
left: win.left,
|
||||||
'popupLoggerBox',
|
top: win.top,
|
||||||
JSON.stringify({
|
width: win.width,
|
||||||
left: win.left,
|
height: win.height,
|
||||||
top: win.top,
|
}));
|
||||||
width: win.width,
|
}
|
||||||
height: win.height,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
callback(response);
|
callback(response);
|
||||||
};
|
};
|
||||||
|
@ -1242,10 +1236,9 @@ const onMessage = function(request, sender, callback) {
|
||||||
µb.logger.ownerId !== undefined &&
|
µb.logger.ownerId !== undefined &&
|
||||||
µb.logger.ownerId !== request.ownerId
|
µb.logger.ownerId !== request.ownerId
|
||||||
) {
|
) {
|
||||||
callback({ unavailable: true });
|
return callback({ unavailable: true });
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
vAPI.tabs.get(null, function(tab) {
|
vAPI.tabs.getCurrent().then(tab => {
|
||||||
getLoggerData(request, tab && tab.id, callback);
|
getLoggerData(request, tab && tab.id, callback);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -106,7 +106,7 @@ const onAllReady = function() {
|
||||||
// in already opened web pages, to remove whatever nuisance could make it to
|
// in already opened web pages, to remove whatever nuisance could make it to
|
||||||
// the web pages before uBlock was ready.
|
// the web pages before uBlock was ready.
|
||||||
|
|
||||||
const initializeTabs = function() {
|
const initializeTabs = async function() {
|
||||||
const handleScriptResponse = function(tabId, results) {
|
const handleScriptResponse = function(tabId, results) {
|
||||||
if (
|
if (
|
||||||
Array.isArray(results) === false ||
|
Array.isArray(results) === false ||
|
||||||
|
@ -128,24 +128,21 @@ const initializeTabs = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const bindToTabs = function(tabs) {
|
const tabs = await vAPI.tabs.query({ url: '<all_urls>' });
|
||||||
for ( const tab of tabs ) {
|
for ( const tab of tabs ) {
|
||||||
µb.tabContextManager.commit(tab.id, tab.url);
|
µb.tabContextManager.commit(tab.id, tab.url);
|
||||||
µb.bindTabToPageStats(tab.id);
|
µb.bindTabToPageStats(tab.id);
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/129
|
// https://github.com/chrisaljoudi/uBlock/issues/129
|
||||||
// Find out whether content scripts need to be injected
|
// Find out whether content scripts need to be injected
|
||||||
// programmatically. This may be necessary for web pages which
|
// programmatically. This may be necessary for web pages which
|
||||||
// were loaded before uBO launched.
|
// were loaded before uBO launched.
|
||||||
if ( /^https?:\/\//.test(tab.url) === false ) { continue; }
|
if ( /^https?:\/\//.test(tab.url) === false ) { continue; }
|
||||||
vAPI.tabs.injectScript(
|
vAPI.tabs.injectScript(
|
||||||
tab.id,
|
tab.id,
|
||||||
{ file: 'js/scriptlets/should-inject-contentscript.js' },
|
{ file: 'js/scriptlets/should-inject-contentscript.js' },
|
||||||
handleScriptResponse.bind(null, tab.id)
|
handleScriptResponse.bind(null, tab.id)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
browser.tabs.query({ url: '<all_urls>' }, bindToTabs);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
@ -542,19 +542,18 @@ housekeep itself.
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TabContext.prototype.onGC = function() {
|
TabContext.prototype.onGC = async function() {
|
||||||
if ( vAPI.isBehindTheSceneTabId(this.tabId) ) { return; }
|
if ( vAPI.isBehindTheSceneTabId(this.tabId) ) { return; }
|
||||||
// https://github.com/gorhill/uBlock/issues/1713
|
// https://github.com/gorhill/uBlock/issues/1713
|
||||||
// For unknown reasons, Firefox's setTimeout() will sometimes
|
// For unknown reasons, Firefox's setTimeout() will sometimes
|
||||||
// causes the callback function to be called immediately, bypassing
|
// causes the callback function to be called immediately, bypassing
|
||||||
// the main event loop. For now this should prevent uBO from crashing
|
// the main event loop. For now this should prevent uBO from crashing
|
||||||
// as a result of the bad setTimeout() behavior.
|
// as a result of the bad setTimeout() behavior.
|
||||||
if ( this.onGCBarrier ) {
|
if ( this.onGCBarrier ) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.onGCBarrier = true;
|
this.onGCBarrier = true;
|
||||||
this.gcTimer = null;
|
this.gcTimer = null;
|
||||||
vAPI.tabs.get(this.tabId, tab => { this.onTab(tab); });
|
const tab = await vAPI.tabs.get(this.tabId);
|
||||||
|
this.onTab(tab);
|
||||||
this.onGCBarrier = false;
|
this.onGCBarrier = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1065,9 +1064,10 @@ vAPI.tabs = new vAPI.Tabs();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateTitle = function(entry) {
|
const updateTitle = async function(entry) {
|
||||||
tabIdToTimer.delete(entry.tabId);
|
tabIdToTimer.delete(entry.tabId);
|
||||||
vAPI.tabs.get(entry.tabId, onTabReady.bind(null, entry));
|
const tab = await vAPI.tabs.get(entry.tabId);
|
||||||
|
onTabReady(entry, tab);
|
||||||
};
|
};
|
||||||
|
|
||||||
return function(tabId) {
|
return function(tabId) {
|
||||||
|
@ -1098,11 +1098,10 @@ vAPI.tabs = new vAPI.Tabs();
|
||||||
|
|
||||||
const pageStoreJanitor = function() {
|
const pageStoreJanitor = function() {
|
||||||
const tabIds = Array.from(µBlock.pageStores.keys()).sort();
|
const tabIds = Array.from(µBlock.pageStores.keys()).sort();
|
||||||
const checkTab = tabId => {
|
const checkTab = async tabId => {
|
||||||
vAPI.tabs.get(tabId, tab => {
|
const tab = await vAPI.tabs.get(tabId);
|
||||||
if ( tab ) { return; }
|
if ( tab ) { return; }
|
||||||
µBlock.unbindTabFromPageStats(tabId);
|
µBlock.unbindTabFromPageStats(tabId);
|
||||||
});
|
|
||||||
};
|
};
|
||||||
if ( pageStoreJanitorSampleAt >= tabIds.length ) {
|
if ( pageStoreJanitorSampleAt >= tabIds.length ) {
|
||||||
pageStoreJanitorSampleAt = 0;
|
pageStoreJanitorSampleAt = 0;
|
||||||
|
|
|
@ -12,11 +12,12 @@ mkdir -p $DES
|
||||||
echo "*** uBlock0.firefox: copying common files"
|
echo "*** uBlock0.firefox: copying common files"
|
||||||
bash ./tools/copy-common-files.sh $DES
|
bash ./tools/copy-common-files.sh $DES
|
||||||
|
|
||||||
cp -R $DES/_locales/nb $DES/_locales/no
|
cp -R $DES/_locales/nb $DES/_locales/no
|
||||||
|
|
||||||
cp platform/firefox/manifest.json $DES/
|
cp platform/firefox/manifest.json $DES/
|
||||||
cp platform/firefox/vapi-usercss.js $DES/js/
|
cp platform/firefox/webext.js $DES/js/
|
||||||
cp platform/firefox/vapi-webrequest.js $DES/js/
|
cp platform/firefox/vapi-usercss.js $DES/js/
|
||||||
|
cp platform/firefox/vapi-webrequest.js $DES/js/
|
||||||
|
|
||||||
echo "*** uBlock0.firefox: concatenating content scripts"
|
echo "*** uBlock0.firefox: concatenating content scripts"
|
||||||
cat $DES/js/vapi-usercss.js > /tmp/contentscript.js
|
cat $DES/js/vapi-usercss.js > /tmp/contentscript.js
|
||||||
|
|
Loading…
Reference in New Issue