From cc03354dd4872662e43b7c5a57aabf60162c5bbb Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 22 Mar 2019 15:01:11 +0000 Subject: [PATCH] Add an IndexedDB existence check to the main store This will be useful for future storage diagnostics as part of https://github.com/vector-im/riot-web/issues/9109. --- src/indexeddb-helpers.js | 50 ++++++++++++++++++++++++++++ src/store/indexeddb-local-backend.js | 5 +++ src/store/indexeddb.js | 4 +++ 3 files changed, 59 insertions(+) create mode 100644 src/indexeddb-helpers.js diff --git a/src/indexeddb-helpers.js b/src/indexeddb-helpers.js new file mode 100644 index 00000000000..55ffb70971c --- /dev/null +++ b/src/indexeddb-helpers.js @@ -0,0 +1,50 @@ +/* +Copyright 2019 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import Promise from 'bluebird'; + +/** + * Check if an IndexedDB database exists. The only way to do so is to try opening it, so + * we do that and then delete it did not exist before. + * + * @param {Object} indexedDB The `indexedDB` interface + * @param {string} dbName The database name to test for + * @returns {boolean} Whether the database exists + */ +export function exists(indexedDB, dbName) { + return new Promise((resolve, reject) => { + let exists = true; + const req = indexedDB.open(dbName); + req.onupgradeneeded = function(ev) { + // Since we did not provide an explicit version when opening, this event + // should only fire if the DB did not exist before at any version. + exists = false; + }; + req.onblocked = () => reject(); + req.onsuccess = function() { + if (!exists) { + // The DB did not exist before, but has been created as part of this + // existence check. Delete it now to restore previous state. Delete can + // actually take a while to complete in some browsers, so don't wait for + // it. This won't block future open calls the might issue next to properly + // set up the DB. + indexedDB.deleteDatabase(dbName); + } + resolve(exists); + }; + req.onerror = ev => reject(ev.target.error); + }); +} diff --git a/src/store/indexeddb-local-backend.js b/src/store/indexeddb-local-backend.js index e3ae1c1aee7..bb1b0abaf63 100644 --- a/src/store/indexeddb-local-backend.js +++ b/src/store/indexeddb-local-backend.js @@ -18,6 +18,7 @@ limitations under the License. import Promise from 'bluebird'; import SyncAccumulator from "../sync-accumulator"; import utils from "../utils"; +import * as IndexedDBHelpers from "../indexeddb-helpers"; const VERSION = 3; @@ -132,6 +133,10 @@ const LocalIndexedDBStoreBackend = function LocalIndexedDBStoreBackend( this._isNewlyCreated = false; }; +LocalIndexedDBStoreBackend.exists = function(indexedDB, dbName) { + dbName = "matrix-js-sdk:" + (dbName || "default"); + return IndexedDBHelpers.exists(indexedDB, dbName); +}; LocalIndexedDBStoreBackend.prototype = { /** diff --git a/src/store/indexeddb.js b/src/store/indexeddb.js index b7f50a316db..7842af5f34f 100644 --- a/src/store/indexeddb.js +++ b/src/store/indexeddb.js @@ -111,6 +111,10 @@ const IndexedDBStore = function IndexedDBStore(opts) { }; utils.inherits(IndexedDBStore, MemoryStore); +IndexedDBStore.exists = function(indexedDB, dbName) { + return LocalIndexedDBStoreBackend.exists(indexedDB, dbName); +}; + /** * @return {Promise} Resolved when loaded from indexed db. */