Add: store the reason why db failed (#550)
* Add: store the reason why db failed * Add: add a warning * fixup! Add: add a warning
This commit is contained in:
parent
deeba1b900
commit
b622ebc172
102
background/db.js
102
background/db.js
|
@ -1,4 +1,4 @@
|
||||||
/* global tryCatch chromeLocal ignoreChromeError */
|
/* global chromeLocal ignoreChromeError workerUtil */
|
||||||
/* 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:
|
||||||
|
@ -18,52 +18,78 @@ const db = (() => {
|
||||||
};
|
};
|
||||||
|
|
||||||
function prepare() {
|
function prepare() {
|
||||||
// we use chrome.storage.local fallback if IndexedDB doesn't save data,
|
return shouldUseIndexedDB().then(
|
||||||
// which, once detected on the first run, is remembered in chrome.storage.local
|
ok => {
|
||||||
// for reliablility and in localStorage for fast synchronous access
|
if (ok) {
|
||||||
// (FF may block localStorage depending on its privacy options)
|
|
||||||
|
|
||||||
// test localStorage
|
|
||||||
const fallbackSet = localStorage.dbInChromeStorage;
|
|
||||||
if (fallbackSet === 'true' || !tryCatch(() => indexedDB)) {
|
|
||||||
useChromeStorage();
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
if (fallbackSet === 'false') {
|
|
||||||
useIndexedDB();
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
// test storage.local
|
|
||||||
return chromeLocal.get('dbInChromeStorage')
|
|
||||||
.then(data =>
|
|
||||||
data && data.dbInChromeStorage && Promise.reject())
|
|
||||||
.then(() =>
|
|
||||||
tryCatch(dbExecIndexedDB, 'getAllKeys', IDBKeyRange.lowerBound(1), 1) ||
|
|
||||||
Promise.reject())
|
|
||||||
.then(({target}) => (
|
|
||||||
(target.result || [])[0] ?
|
|
||||||
Promise.reject('ok') :
|
|
||||||
dbExecIndexedDB('put', {id: -1})))
|
|
||||||
.then(() =>
|
|
||||||
dbExecIndexedDB('get', -1))
|
|
||||||
.then(({target}) => (
|
|
||||||
(target.result || {}).id === -1 ?
|
|
||||||
dbExecIndexedDB('delete', -1) :
|
|
||||||
Promise.reject()))
|
|
||||||
.then(() =>
|
|
||||||
Promise.reject('ok'))
|
|
||||||
.catch(result => {
|
|
||||||
if (result === 'ok') {
|
|
||||||
useIndexedDB();
|
useIndexedDB();
|
||||||
} else {
|
} else {
|
||||||
useChromeStorage();
|
useChromeStorage();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
useChromeStorage(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldUseIndexedDB() {
|
||||||
|
// 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
|
||||||
|
// for reliablility and in localStorage for fast synchronous access
|
||||||
|
// (FF may block localStorage depending on its privacy options)
|
||||||
|
if (typeof indexedDB === 'undefined') {
|
||||||
|
return Promise.reject(new Error('indexedDB is undefined'));
|
||||||
|
}
|
||||||
|
// test localStorage
|
||||||
|
const fallbackSet = localStorage.dbInChromeStorage;
|
||||||
|
if (fallbackSet === 'true') {
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
if (fallbackSet === 'false') {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
// test storage.local
|
||||||
|
return chromeLocal.get('dbInChromeStorage')
|
||||||
|
.then(data => {
|
||||||
|
if (data && data.dbInChromeStorage) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return testDBSize()
|
||||||
|
.then(ok => ok || testDBMutation());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function useChromeStorage() {
|
function testDBSize() {
|
||||||
|
return dbExecIndexedDB('getAllKeys', IDBKeyRange.lowerBound(1), 1)
|
||||||
|
.then(event => (
|
||||||
|
event.target.result &&
|
||||||
|
event.target.result.length &&
|
||||||
|
event.target.result[0]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
exec = dbExecChromeStorage;
|
exec = dbExecChromeStorage;
|
||||||
chromeLocal.set({dbInChromeStorage: true}, ignoreChromeError);
|
chromeLocal.set({dbInChromeStorage: true}, ignoreChromeError);
|
||||||
|
if (err) {
|
||||||
|
chromeLocal.setValue('dbInChromeStorageReason', workerUtil.cloneError(err));
|
||||||
|
console.warn('Failed to access indexedDB. Switched to storage API.', err);
|
||||||
|
}
|
||||||
localStorage.dbInChromeStorage = 'true';
|
localStorage.dbInChromeStorage = 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user