mirror of
https://github.com/gorhill/uBlock.git
synced 2026-03-11 09:04:36 +00:00
Remove usage of synchronous localStorage API
Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/899 browser.storage.local is now used to store non-critical local settings. These settings are all collated under the key `localStorage`, and vAPI.localStorage is an API to handle access to these values stored under this key. vAPI.localStorage.getItem() is still synchronous but its purpose is to return internally cached values -- this minimizes code changes throughout uBO.
This commit is contained in:
parent
5da3aaaabf
commit
2ac288397c
9 changed files with 144 additions and 123 deletions
|
|
@ -218,48 +218,92 @@ vAPI.closePopup = function() {
|
||||||
// background page or auxiliary pages.
|
// background page or auxiliary pages.
|
||||||
// This storage is optional, but it is nice to have, for a more polished user
|
// This storage is optional, but it is nice to have, for a more polished user
|
||||||
// experience.
|
// experience.
|
||||||
|
//
|
||||||
// https://github.com/gorhill/uBlock/issues/2824
|
// https://github.com/gorhill/uBlock/issues/2824
|
||||||
// Use a dummy localStorage if for some reasons it's not available.
|
// Use a dummy localStorage if for some reasons it's not available.
|
||||||
|
//
|
||||||
// https://github.com/gorhill/uMatrix/issues/840
|
// https://github.com/gorhill/uMatrix/issues/840
|
||||||
// Always use a wrapper to seamlessly handle exceptions
|
// Always use a wrapper to seamlessly handle exceptions
|
||||||
|
//
|
||||||
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/899
|
||||||
|
// Convert into asynchronous access API.
|
||||||
|
|
||||||
vAPI.localStorage = {
|
vAPI.localStorage = {
|
||||||
started: false,
|
|
||||||
start: function() {
|
start: function() {
|
||||||
this.started = true;
|
if ( this.cache instanceof Object ) { return Promise.resolve(); }
|
||||||
|
if ( this.promise !== undefined ) { return this.promise; }
|
||||||
|
this.promise = new Promise(resolve => {
|
||||||
|
browser.storage.local.get('localStorage', bin => {
|
||||||
|
if (
|
||||||
|
bin instanceof Object === false ||
|
||||||
|
bin.localStorage instanceof Object === false
|
||||||
|
) {
|
||||||
|
this.cache = {};
|
||||||
|
const ls = self.localStorage;
|
||||||
|
for ( let i = 0; i < ls.length; i++ ) {
|
||||||
|
const key = ls.key(i);
|
||||||
|
this.cache[key] = ls.getItem(key);
|
||||||
|
}
|
||||||
|
//ls.clear();
|
||||||
|
browser.storage.local.set({ localStorage: this.cache });
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
this.cache = bin.localStorage;
|
||||||
|
} catch(ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( this.cache instanceof Object === false ) {
|
||||||
|
this.cache = {};
|
||||||
|
}
|
||||||
|
this.promise = undefined;
|
||||||
|
browser.storage.onChanged.addListener((changes, area) => {
|
||||||
|
if (
|
||||||
|
area !== 'local' ||
|
||||||
|
changes instanceof Object === false ||
|
||||||
|
changes.localStorage instanceof Object === false
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newValue = changes.localStorage.newValue;
|
||||||
|
this.cache = newValue instanceof Object ? newValue : {};
|
||||||
|
});
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return this.promise;
|
||||||
},
|
},
|
||||||
clear: function() {
|
clear: function() {
|
||||||
try {
|
this.cache = {};
|
||||||
window.localStorage.clear();
|
return browser.storage.local.set({ localStorage: this.cache });
|
||||||
} catch(ex) {
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
getItem: function(key) {
|
getItem: function(key) {
|
||||||
if ( this.started === false ) { return null; }
|
if ( this.cache instanceof Object === false ) {
|
||||||
try {
|
console.info(`localStorage.getItem('${key}') not ready`);
|
||||||
return window.localStorage.getItem(key);
|
return null;
|
||||||
} catch(ex) {
|
|
||||||
}
|
}
|
||||||
return null;
|
const value = this.cache[key];
|
||||||
|
return value !== undefined ? value : null;
|
||||||
|
},
|
||||||
|
getItemAsync: function(key) {
|
||||||
|
return this.start().then(( ) => {
|
||||||
|
const value = this.cache[key];
|
||||||
|
return value !== undefined ? value : null;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
removeItem: function(key) {
|
removeItem: function(key) {
|
||||||
try {
|
this.setItem(key);
|
||||||
window.localStorage.removeItem(key);
|
|
||||||
} catch(ex) {
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
setItem: function(key, value) {
|
setItem: function(key, value = undefined) {
|
||||||
if ( this.started === false ) { return; }
|
return this.start().then(( ) => {
|
||||||
try {
|
this.cache[key] = value;
|
||||||
window.localStorage.setItem(key, value);
|
return browser.storage.local.set({ localStorage: this.cache });
|
||||||
} catch(ex) {
|
});
|
||||||
}
|
},
|
||||||
}
|
promise: undefined,
|
||||||
|
cache: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vAPI.localStorage.start();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,20 +45,6 @@ let cachedUserFilters = '';
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/3706
|
|
||||||
// Save/restore cursor position
|
|
||||||
//
|
|
||||||
// CoreMirror reference: https://codemirror.net/doc/manual.html#api_selection
|
|
||||||
|
|
||||||
window.addEventListener('beforeunload', ( ) => {
|
|
||||||
vAPI.localStorage.setItem(
|
|
||||||
'myFiltersCursorPosition',
|
|
||||||
JSON.stringify(cmEditor.getCursor().line)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// This is to give a visual hint that the content of user blacklist has changed.
|
// This is to give a visual hint that the content of user blacklist has changed.
|
||||||
|
|
||||||
const userFiltersChanged = function(changed) {
|
const userFiltersChanged = function(changed) {
|
||||||
|
|
@ -71,7 +57,7 @@ const userFiltersChanged = function(changed) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
const renderUserFilters = async function(first) {
|
const renderUserFilters = async function() {
|
||||||
const details = await vAPI.messaging.send('dashboard', {
|
const details = await vAPI.messaging.send('dashboard', {
|
||||||
what: 'readUserFilters',
|
what: 'readUserFilters',
|
||||||
});
|
});
|
||||||
|
|
@ -83,18 +69,7 @@ const renderUserFilters = async function(first) {
|
||||||
content += '\n';
|
content += '\n';
|
||||||
}
|
}
|
||||||
cmEditor.setValue(content);
|
cmEditor.setValue(content);
|
||||||
if ( first ) {
|
|
||||||
cmEditor.clearHistory();
|
|
||||||
try {
|
|
||||||
const line = JSON.parse(
|
|
||||||
vAPI.localStorage.getItem('myFiltersCursorPosition')
|
|
||||||
);
|
|
||||||
if ( typeof line === 'number' ) {
|
|
||||||
cmEditor.setCursor(line, 0);
|
|
||||||
}
|
|
||||||
} catch(ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
userFiltersChanged(false);
|
userFiltersChanged(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -224,7 +199,24 @@ uDom('#exportUserFiltersToFile').on('click', exportUserFiltersToFile);
|
||||||
uDom('#userFiltersApply').on('click', ( ) => { applyChanges(); });
|
uDom('#userFiltersApply').on('click', ( ) => { applyChanges(); });
|
||||||
uDom('#userFiltersRevert').on('click', revertChanges);
|
uDom('#userFiltersRevert').on('click', revertChanges);
|
||||||
|
|
||||||
renderUserFilters(true);
|
// https://github.com/gorhill/uBlock/issues/3706
|
||||||
|
// Save/restore cursor position
|
||||||
|
//
|
||||||
|
// CoreMirror reference: https://codemirror.net/doc/manual.html#api_selection
|
||||||
|
renderUserFilters().then(( ) => {
|
||||||
|
cmEditor.clearHistory();
|
||||||
|
return vAPI.localStorage.getItemAsync('myFiltersCursorPosition');
|
||||||
|
}).then(line => {
|
||||||
|
if ( typeof line === 'number' ) {
|
||||||
|
cmEditor.setCursor(line, 0);
|
||||||
|
}
|
||||||
|
cmEditor.on('cursorActivity', ( ) => {
|
||||||
|
const line = cmEditor.getCursor().line;
|
||||||
|
if ( vAPI.localStorage.getItem('myFiltersCursorPosition') !== line ) {
|
||||||
|
vAPI.localStorage.setItem('myFiltersCursorPosition', line);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
cmEditor.on('changes', userFiltersChanged);
|
cmEditor.on('changes', userFiltersChanged);
|
||||||
CodeMirror.commands.save = applyChanges;
|
CodeMirror.commands.save = applyChanges;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ const reValidExternalList = /[a-z-]+:\/\/\S*\/\S+/;
|
||||||
|
|
||||||
let listDetails = {};
|
let listDetails = {};
|
||||||
let filteringSettingsHash = '';
|
let filteringSettingsHash = '';
|
||||||
let hideUnusedSet = new Set();
|
let hideUnusedSet = new Set([ '*' ]);
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
@ -258,10 +258,6 @@ const renderFilterLists = function(soft) {
|
||||||
let groupKey = groupKeys[i];
|
let groupKey = groupKeys[i];
|
||||||
let liGroup = liFromListGroup(groupKey, groups.get(groupKey));
|
let liGroup = liFromListGroup(groupKey, groups.get(groupKey));
|
||||||
liGroup.setAttribute('data-groupkey', groupKey);
|
liGroup.setAttribute('data-groupkey', groupKey);
|
||||||
liGroup.classList.toggle(
|
|
||||||
'collapsed',
|
|
||||||
vAPI.localStorage.getItem('collapseGroup' + (i + 1)) === 'y'
|
|
||||||
);
|
|
||||||
if ( liGroup.parentElement === null ) {
|
if ( liGroup.parentElement === null ) {
|
||||||
ulLists.appendChild(liGroup);
|
ulLists.appendChild(liGroup);
|
||||||
}
|
}
|
||||||
|
|
@ -548,7 +544,7 @@ const toggleHideUnusedLists = function(which) {
|
||||||
.toggleClass('unused', mustHide);
|
.toggleClass('unused', mustHide);
|
||||||
vAPI.localStorage.setItem(
|
vAPI.localStorage.setItem(
|
||||||
'hideUnusedFilterLists',
|
'hideUnusedFilterLists',
|
||||||
JSON.stringify(Array.from(hideUnusedSet))
|
Array.from(hideUnusedSet)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -571,20 +567,11 @@ uDom('#lists').on('click', '.groupEntry[data-groupkey] > .geDetails', function(e
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize from saved state.
|
// Initialize from saved state.
|
||||||
{
|
vAPI.localStorage.getItemAsync('hideUnusedFilterLists').then(value => {
|
||||||
let aa;
|
if ( Array.isArray(value) ) {
|
||||||
try {
|
hideUnusedSet = new Set(value);
|
||||||
const json = vAPI.localStorage.getItem('hideUnusedFilterLists');
|
|
||||||
if ( json !== null ) {
|
|
||||||
aa = JSON.parse(json);
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
}
|
}
|
||||||
if ( Array.isArray(aa) === false ) {
|
});
|
||||||
aa = [ '*' ];
|
|
||||||
}
|
|
||||||
hideUnusedSet = new Set(aa);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,10 +84,10 @@ const discardUnsavedData = function(synchronous = false) {
|
||||||
|
|
||||||
const loadDashboardPanel = function(pane = '') {
|
const loadDashboardPanel = function(pane = '') {
|
||||||
if ( pane === '' ) {
|
if ( pane === '' ) {
|
||||||
pane = vAPI.localStorage.getItem('dashboardLastVisitedPane');
|
vAPI.localStorage.getItemAsync('dashboardLastVisitedPane').then(value => {
|
||||||
if ( pane === null ) {
|
loadDashboardPanel(value !== null ? value : 'settings.html');
|
||||||
pane = 'settings.html';
|
});
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
const tabButton = uDom(`[href="#${pane}"]`);
|
const tabButton = uDom(`[href="#${pane}"]`);
|
||||||
if ( !tabButton || tabButton.hasClass('selected') ) { return; }
|
if ( !tabButton || tabButton.hasClass('selected') ) { return; }
|
||||||
|
|
|
||||||
|
|
@ -194,10 +194,12 @@ uDom.nodeFromId('why').textContent = details.fs;
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
uDom.nodeFromId('theURL').classList.toggle(
|
vAPI.localStorage.getItemAsync('document-blocked-expand-url').then(value => {
|
||||||
'collapsed',
|
uDom.nodeFromId('theURL').classList.toggle(
|
||||||
vAPI.localStorage.getItem('document-blocked-expand-url') !== 'true'
|
'collapsed',
|
||||||
);
|
value !== 'true' && value !== true
|
||||||
|
);
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
||||||
|
|
@ -2675,9 +2675,9 @@ const loggerSettings = (( ) => {
|
||||||
linesPerEntry: 4,
|
linesPerEntry: 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
vAPI.localStorage.getItemAsync('loggerSettings').then(value => {
|
||||||
try {
|
try {
|
||||||
const stored = JSON.parse(vAPI.localStorage.getItem('loggerSettings'));
|
const stored = JSON.parse(value);
|
||||||
if ( typeof stored.discard.maxAge === 'number' ) {
|
if ( typeof stored.discard.maxAge === 'number' ) {
|
||||||
settings.discard.maxAge = stored.discard.maxAge;
|
settings.discard.maxAge = stored.discard.maxAge;
|
||||||
}
|
}
|
||||||
|
|
@ -2695,7 +2695,7 @@ const loggerSettings = (( ) => {
|
||||||
}
|
}
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
const valueFromInput = function(input, def) {
|
const valueFromInput = function(input, def) {
|
||||||
let value = parseInt(input.value, 10);
|
let value = parseInt(input.value, 10);
|
||||||
|
|
|
||||||
|
|
@ -30,19 +30,23 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
let popupFontSize = vAPI.localStorage.getItem('popupFontSize');
|
let popupFontSize;
|
||||||
if ( typeof popupFontSize === 'string' && popupFontSize !== 'unset' ) {
|
vAPI.localStorage.getItemAsync('popupFontSize').then(value => {
|
||||||
document.body.style.setProperty('font-size', popupFontSize);
|
if ( typeof value !== 'string' || value === 'unset' ) { return; }
|
||||||
}
|
document.body.style.setProperty('font-size', value);
|
||||||
|
popupFontSize = value;
|
||||||
|
});
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/996
|
// https://github.com/chrisaljoudi/uBlock/issues/996
|
||||||
// Experimental: mitigate glitchy popup UI: immediately set the firewall
|
// Experimental: mitigate glitchy popup UI: immediately set the firewall
|
||||||
// pane visibility to its last known state. By default the pane is hidden.
|
// pane visibility to its last known state. By default the pane is hidden.
|
||||||
let dfPaneVisibleStored =
|
let dfPaneVisibleStored;
|
||||||
vAPI.localStorage.getItem('popupFirewallPane') === 'true';
|
vAPI.localStorage.getItemAsync('popupFirewallPane').then(value => {
|
||||||
if ( dfPaneVisibleStored ) {
|
dfPaneVisibleStored = value === true || value === 'true';
|
||||||
document.getElementById('main').classList.add('dfEnabled');
|
if ( dfPaneVisibleStored ) {
|
||||||
}
|
document.getElementById('panes').classList.add('dfEnabled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
@ -838,11 +842,8 @@ document.addEventListener(
|
||||||
|
|
||||||
const expandExceptions = new Set();
|
const expandExceptions = new Set();
|
||||||
|
|
||||||
(( ) => {
|
vAPI.localStorage.getItemAsync('popupExpandExceptions').then(exceptions => {
|
||||||
try {
|
try {
|
||||||
const exceptions = JSON.parse(
|
|
||||||
vAPI.localStorage.getItem('popupExpandExceptions')
|
|
||||||
);
|
|
||||||
if ( Array.isArray(exceptions) === false ) { return; }
|
if ( Array.isArray(exceptions) === false ) { return; }
|
||||||
for ( const exception of exceptions ) {
|
for ( const exception of exceptions ) {
|
||||||
expandExceptions.add(exception);
|
expandExceptions.add(exception);
|
||||||
|
|
@ -850,13 +851,12 @@ const expandExceptions = new Set();
|
||||||
}
|
}
|
||||||
catch(ex) {
|
catch(ex) {
|
||||||
}
|
}
|
||||||
|
});
|
||||||
})();
|
|
||||||
|
|
||||||
const saveExpandExceptions = function() {
|
const saveExpandExceptions = function() {
|
||||||
vAPI.localStorage.setItem(
|
vAPI.localStorage.setItem(
|
||||||
'popupExpandExceptions',
|
'popupExpandExceptions',
|
||||||
JSON.stringify(Array.from(expandExceptions))
|
Array.from(expandExceptions)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,12 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
let popupFontSize = vAPI.localStorage.getItem('popupFontSize');
|
let popupFontSize;
|
||||||
if ( typeof popupFontSize === 'string' && popupFontSize !== 'unset' ) {
|
vAPI.localStorage.getItemAsync('popupFontSize').then(value => {
|
||||||
document.body.style.setProperty('font-size', popupFontSize);
|
if ( typeof value !== 'string' || value === 'unset' ) { return; }
|
||||||
}
|
document.body.style.setProperty('font-size', value);
|
||||||
|
popupFontSize = value;
|
||||||
|
});
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/3032
|
// https://github.com/gorhill/uBlock/issues/3032
|
||||||
// Popup panel can be in one of two modes:
|
// Popup panel can be in one of two modes:
|
||||||
|
|
@ -48,13 +50,15 @@ if (
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/996
|
// https://github.com/chrisaljoudi/uBlock/issues/996
|
||||||
// Experimental: mitigate glitchy popup UI: immediately set the firewall
|
// Experimental: mitigate glitchy popup UI: immediately set the firewall
|
||||||
// pane visibility to its last known state. By default the pane is hidden.
|
// pane visibility to its last known state. By default the pane is hidden.
|
||||||
let dfPaneVisibleStored =
|
let dfPaneVisibleStored;
|
||||||
vAPI.localStorage.getItem('popupFirewallPane') === 'true';
|
vAPI.localStorage.getItemAsync('popupFirewallPane').then(value => {
|
||||||
if ( dfPaneVisibleStored ) {
|
dfPaneVisibleStored = value === true || value === 'true';
|
||||||
document.getElementById('panes').classList.add('dfEnabled');
|
if ( dfPaneVisibleStored ) {
|
||||||
}
|
document.getElementById('panes').classList.add('dfEnabled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
@ -931,11 +935,8 @@ document.addEventListener(
|
||||||
|
|
||||||
const expandExceptions = new Set();
|
const expandExceptions = new Set();
|
||||||
|
|
||||||
(( ) => {
|
vAPI.localStorage.getItemAsync('popupExpandExceptions').then(exceptions => {
|
||||||
try {
|
try {
|
||||||
const exceptions = JSON.parse(
|
|
||||||
vAPI.localStorage.getItem('popupExpandExceptions')
|
|
||||||
);
|
|
||||||
if ( Array.isArray(exceptions) === false ) { return; }
|
if ( Array.isArray(exceptions) === false ) { return; }
|
||||||
for ( const exception of exceptions ) {
|
for ( const exception of exceptions ) {
|
||||||
expandExceptions.add(exception);
|
expandExceptions.add(exception);
|
||||||
|
|
@ -943,13 +944,12 @@ const expandExceptions = new Set();
|
||||||
}
|
}
|
||||||
catch(ex) {
|
catch(ex) {
|
||||||
}
|
}
|
||||||
|
});
|
||||||
})();
|
|
||||||
|
|
||||||
const saveExpandExceptions = function() {
|
const saveExpandExceptions = function() {
|
||||||
vAPI.localStorage.setItem(
|
vAPI.localStorage.setItem(
|
||||||
'popupExpandExceptions',
|
'popupExpandExceptions',
|
||||||
JSON.stringify(Array.from(expandExceptions))
|
Array.from(expandExceptions)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -316,10 +316,6 @@ if ( selfieIsValid !== true ) {
|
||||||
// Start network observers.
|
// Start network observers.
|
||||||
µb.webRequest.start();
|
µb.webRequest.start();
|
||||||
|
|
||||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/899
|
|
||||||
// Signal that localStorage can be used now that uBO is ready.
|
|
||||||
vAPI.localStorage.start();
|
|
||||||
|
|
||||||
// Ensure that the resources allocated for decompression purpose (likely
|
// Ensure that the resources allocated for decompression purpose (likely
|
||||||
// large buffers) are garbage-collectable immediately after launch.
|
// large buffers) are garbage-collectable immediately after launch.
|
||||||
// Otherwise I have observed that it may take quite a while before the
|
// Otherwise I have observed that it may take quite a while before the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue