cleanup usoSearchCache + tidy up db.js
This commit is contained in:
parent
a01bd3cd61
commit
b840d4897d
|
@ -1,5 +1,5 @@
|
||||||
/* global download prefs openURL FIREFOX CHROME
|
/* global download prefs openURL FIREFOX CHROME
|
||||||
URLS ignoreChromeError usercssHelper
|
URLS ignoreChromeError usercssHelper chromeLocal semverCompare
|
||||||
styleManager msg navigatorUtil workerUtil contentScripts sync
|
styleManager msg navigatorUtil workerUtil contentScripts sync
|
||||||
findExistingTab activateTab isTabReplaceable getActiveTab
|
findExistingTab activateTab isTabReplaceable getActiveTab
|
||||||
tabManager */
|
tabManager */
|
||||||
|
@ -139,7 +139,7 @@ if (chrome.commands) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// *************************************************************************
|
// *************************************************************************
|
||||||
chrome.runtime.onInstalled.addListener(({reason}) => {
|
chrome.runtime.onInstalled.addListener(({reason, previousVersion}) => {
|
||||||
// save install type: "admin", "development", "normal", "sideload" or "other"
|
// save install type: "admin", "development", "normal", "sideload" or "other"
|
||||||
// "normal" = addon installed from webstore
|
// "normal" = addon installed from webstore
|
||||||
chrome.management.getSelf(info => {
|
chrome.management.getSelf(info => {
|
||||||
|
@ -156,6 +156,14 @@ chrome.runtime.onInstalled.addListener(({reason}) => {
|
||||||
});
|
});
|
||||||
// themes may change
|
// themes may change
|
||||||
delete localStorage.codeMirrorThemes;
|
delete localStorage.codeMirrorThemes;
|
||||||
|
// inline search cache for USO is not needed anymore, TODO: remove this by the middle of 2021
|
||||||
|
if (semverCompare(previousVersion, '1.5.13') <= 0) {
|
||||||
|
setTimeout(async () => {
|
||||||
|
const del = Object.keys(await chromeLocal.get())
|
||||||
|
.filter(key => key.startsWith('usoSearchCache'));
|
||||||
|
if (del.length) chromeLocal.remove(del);
|
||||||
|
}, 15e3);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// *************************************************************************
|
// *************************************************************************
|
||||||
|
|
179
background/db.js
179
background/db.js
|
@ -1,4 +1,4 @@
|
||||||
/* global chromeLocal ignoreChromeError workerUtil createChromeStorageDB */
|
/* global chromeLocal workerUtil createChromeStorageDB */
|
||||||
/* exported db */
|
/* exported db */
|
||||||
/*
|
/*
|
||||||
Initialize a database. There are some problems using IndexedDB in Firefox:
|
Initialize a database. There are some problems using IndexedDB in Firefox:
|
||||||
|
@ -10,29 +10,18 @@ https://www.reddit.com/r/firefox/comments/7ijuaq/firefox_59_webextensions_can_us
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const db = (() => {
|
const db = (() => {
|
||||||
let exec;
|
const DATABASE = 'stylish';
|
||||||
const preparing = prepare();
|
const STORE = 'styles';
|
||||||
return {
|
const FALLBACK = 'dbInChromeStorage';
|
||||||
exec: (...args) =>
|
const dbApi = {
|
||||||
preparing.then(() => exec(...args))
|
async exec(...args) {
|
||||||
|
dbApi.exec = await tryUsingIndexedDB().catch(useChromeStorage);
|
||||||
|
return dbApi.exec(...args);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
return dbApi;
|
||||||
|
|
||||||
function prepare() {
|
async function tryUsingIndexedDB() {
|
||||||
return withPromise(shouldUseIndexedDB).then(
|
|
||||||
ok => {
|
|
||||||
if (ok) {
|
|
||||||
useIndexedDB();
|
|
||||||
} else {
|
|
||||||
useChromeStorage();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
useChromeStorage(err);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldUseIndexedDB() {
|
|
||||||
// we use chrome.storage.local fallback if IndexedDB doesn't save data,
|
// we use chrome.storage.local fallback if IndexedDB doesn't save data,
|
||||||
// which, once detected on the first run, is remembered in chrome.storage.local
|
// which, once detected on the first run, is remembered in chrome.storage.local
|
||||||
// for reliablility and in localStorage for fast synchronous access
|
// for reliablility and in localStorage for fast synchronous access
|
||||||
|
@ -42,115 +31,81 @@ const db = (() => {
|
||||||
if (typeof indexedDB === 'undefined') {
|
if (typeof indexedDB === 'undefined') {
|
||||||
throw new Error('indexedDB is undefined');
|
throw new Error('indexedDB is undefined');
|
||||||
}
|
}
|
||||||
// test localStorage
|
switch (await getFallback()) {
|
||||||
const fallbackSet = localStorage.dbInChromeStorage;
|
case true: throw null;
|
||||||
if (fallbackSet === 'true') {
|
case false: break;
|
||||||
return false;
|
default: await testDB();
|
||||||
}
|
}
|
||||||
if (fallbackSet === 'false') {
|
return useIndexedDB();
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// test storage.local
|
|
||||||
return chromeLocal.get('dbInChromeStorage')
|
|
||||||
.then(data => {
|
|
||||||
if (data && data.dbInChromeStorage) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return testDBSize()
|
|
||||||
.then(ok => ok || testDBMutation());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function withPromise(fn) {
|
async function getFallback() {
|
||||||
try {
|
return localStorage[FALLBACK] === 'true' ? true :
|
||||||
return Promise.resolve(fn());
|
localStorage[FALLBACK] === 'false' ? false :
|
||||||
} catch (err) {
|
chromeLocal.getValue(FALLBACK);
|
||||||
return Promise.reject(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDBSize() {
|
async function testDB() {
|
||||||
return dbExecIndexedDB('getAllKeys', IDBKeyRange.lowerBound(1), 1)
|
let e = await dbExecIndexedDB('getAllKeys', IDBKeyRange.lowerBound(1), 1);
|
||||||
.then(event => (
|
// throws if result is null
|
||||||
event.target.result &&
|
e = e.target.result[0];
|
||||||
event.target.result.length &&
|
const id = `${performance.now()}.${Math.random()}.${Date.now()}`;
|
||||||
event.target.result[0]
|
await dbExecIndexedDB('put', {id});
|
||||||
));
|
e = await dbExecIndexedDB('get', id);
|
||||||
}
|
// throws if result or id is null
|
||||||
|
await dbExecIndexedDB('delete', e.target.result.id);
|
||||||
function testDBMutation() {
|
|
||||||
return dbExecIndexedDB('put', {id: -1})
|
|
||||||
.then(() => dbExecIndexedDB('get', -1))
|
|
||||||
.then(event => {
|
|
||||||
if (!event.target.result) {
|
|
||||||
throw new Error('failed to get previously put item');
|
|
||||||
}
|
|
||||||
if (event.target.result.id !== -1) {
|
|
||||||
throw new Error('item id is wrong');
|
|
||||||
}
|
|
||||||
return dbExecIndexedDB('delete', -1);
|
|
||||||
})
|
|
||||||
.then(() => true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function useChromeStorage(err) {
|
function useChromeStorage(err) {
|
||||||
exec = createChromeStorageDB().exec;
|
chromeLocal.setValue(FALLBACK, true);
|
||||||
chromeLocal.set({dbInChromeStorage: true}, ignoreChromeError);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
chromeLocal.setValue('dbInChromeStorageReason', workerUtil.cloneError(err));
|
chromeLocal.setValue(FALLBACK + 'Reason', workerUtil.cloneError(err));
|
||||||
console.warn('Failed to access indexedDB. Switched to storage API.', err);
|
console.warn('Failed to access indexedDB. Switched to storage API.', err);
|
||||||
}
|
}
|
||||||
localStorage.dbInChromeStorage = 'true';
|
localStorage[FALLBACK] = 'true';
|
||||||
|
return createChromeStorageDB().exec;
|
||||||
}
|
}
|
||||||
|
|
||||||
function useIndexedDB() {
|
function useIndexedDB() {
|
||||||
exec = dbExecIndexedDB;
|
chromeLocal.setValue(FALLBACK, false);
|
||||||
chromeLocal.set({dbInChromeStorage: false}, ignoreChromeError);
|
localStorage[FALLBACK] = 'false';
|
||||||
localStorage.dbInChromeStorage = 'false';
|
return dbExecIndexedDB;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbExecIndexedDB(method, ...args) {
|
async function dbExecIndexedDB(method, ...args) {
|
||||||
return open().then(database => {
|
const mode = method.startsWith('get') ? 'readonly' : 'readwrite';
|
||||||
if (!method) {
|
const store = (await open()).transaction([STORE], mode).objectStore(STORE);
|
||||||
return database;
|
const fn = method === 'putMany' ? putMany : storeRequest;
|
||||||
}
|
return fn(store, method, ...args);
|
||||||
if (method === 'putMany') {
|
}
|
||||||
return putMany(database, ...args);
|
|
||||||
}
|
function storeRequest(store, method, ...args) {
|
||||||
const mode = method.startsWith('get') ? 'readonly' : 'readwrite';
|
return new Promise((resolve, reject) => {
|
||||||
const transaction = database.transaction(['styles'], mode);
|
const request = store[method](...args);
|
||||||
const store = transaction.objectStore('styles');
|
request.onsuccess = resolve;
|
||||||
return storeRequest(store, method, ...args);
|
request.onerror = reject;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function storeRequest(store, method, ...args) {
|
function putMany(store, _method, items) {
|
||||||
return new Promise((resolve, reject) => {
|
return Promise.all(items.map(item => storeRequest(store, 'put', item)));
|
||||||
const request = store[method](...args);
|
}
|
||||||
request.onsuccess = resolve;
|
|
||||||
request.onerror = reject;
|
function open() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const request = indexedDB.open(DATABASE, 2);
|
||||||
|
request.onsuccess = () => resolve(request.result);
|
||||||
|
request.onerror = reject;
|
||||||
|
request.onupgradeneeded = create;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function create(event) {
|
||||||
|
if (event.oldVersion === 0) {
|
||||||
|
event.target.result.createObjectStore(STORE, {
|
||||||
|
keyPath: 'id',
|
||||||
|
autoIncrement: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function open() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const request = indexedDB.open('stylish', 2);
|
|
||||||
request.onsuccess = () => resolve(request.result);
|
|
||||||
request.onerror = reject;
|
|
||||||
request.onupgradeneeded = event => {
|
|
||||||
if (event.oldVersion === 0) {
|
|
||||||
event.target.result.createObjectStore('styles', {
|
|
||||||
keyPath: 'id',
|
|
||||||
autoIncrement: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function putMany(database, items) {
|
|
||||||
const transaction = database.transaction(['styles'], 'readwrite');
|
|
||||||
const store = transaction.objectStore('styles');
|
|
||||||
return Promise.all(items.map(item => storeRequest(store, 'put', item)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user