dom/base/IndexedDBHelper.jsm

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/base/IndexedDBHelper.jsm	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,168 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +"use strict";
     1.9 +
    1.10 +let DEBUG = 0;
    1.11 +let debug;
    1.12 +if (DEBUG) {
    1.13 +  debug = function (s) { dump("-*- IndexedDBHelper: " + s + "\n"); }
    1.14 +} else {
    1.15 +  debug = function (s) {}
    1.16 +}
    1.17 +
    1.18 +const Cu = Components.utils;
    1.19 +const Cc = Components.classes;
    1.20 +const Ci = Components.interfaces;
    1.21 +
    1.22 +this.EXPORTED_SYMBOLS = ["IndexedDBHelper"];
    1.23 +
    1.24 +Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    1.25 +Cu.import("resource://gre/modules/Services.jsm");
    1.26 +Cu.importGlobalProperties(["indexedDB"]);
    1.27 +
    1.28 +this.IndexedDBHelper = function IndexedDBHelper() {}
    1.29 +
    1.30 +IndexedDBHelper.prototype = {
    1.31 +
    1.32 +  // Cache the database
    1.33 +  _db: null,
    1.34 +
    1.35 +  // Close the database
    1.36 +  close: function close() {
    1.37 +    if (this._db) {
    1.38 +      this._db.close();
    1.39 +      this._db = null;
    1.40 +    }
    1.41 +  },
    1.42 +
    1.43 +  /**
    1.44 +   * Open a new database.
    1.45 +   * User has to provide upgradeSchema.
    1.46 +   *
    1.47 +   * @param successCb
    1.48 +   *        Success callback to call once database is open.
    1.49 +   * @param failureCb
    1.50 +   *        Error callback to call when an error is encountered.
    1.51 +   */
    1.52 +  open: function open(aSuccessCb, aFailureCb) {
    1.53 +    let self = this;
    1.54 +    if (DEBUG) debug("Try to open database:" + self.dbName + " " + self.dbVersion);
    1.55 +    let req = indexedDB.open(this.dbName, this.dbVersion);
    1.56 +    req.onsuccess = function (event) {
    1.57 +      if (DEBUG) debug("Opened database:" + self.dbName + " " + self.dbVersion);
    1.58 +      self._db = event.target.result;
    1.59 +      self._db.onversionchange = function(event) {
    1.60 +        if (DEBUG) debug("WARNING: DB modified from a different window.");
    1.61 +      }
    1.62 +      aSuccessCb && aSuccessCb();
    1.63 +    };
    1.64 +
    1.65 +    req.onupgradeneeded = function (aEvent) {
    1.66 +      if (DEBUG) {
    1.67 +        debug("Database needs upgrade:" + self.dbName + aEvent.oldVersion + aEvent.newVersion);
    1.68 +        debug("Correct new database version:" + (aEvent.newVersion == this.dbVersion));
    1.69 +      }
    1.70 +
    1.71 +      let _db = aEvent.target.result;
    1.72 +      self.upgradeSchema(req.transaction, _db, aEvent.oldVersion, aEvent.newVersion);
    1.73 +    };
    1.74 +    req.onerror = function (aEvent) {
    1.75 +      if (DEBUG) debug("Failed to open database: " + self.dbName);
    1.76 +      aFailureCb && aFailureCb(aEvent.target.error.name);
    1.77 +    };
    1.78 +    req.onblocked = function (aEvent) {
    1.79 +      if (DEBUG) debug("Opening database request is blocked.");
    1.80 +    };
    1.81 +  },
    1.82 +
    1.83 +  /**
    1.84 +   * Use the cached DB or open a new one.
    1.85 +   *
    1.86 +   * @param successCb
    1.87 +   *        Success callback to call.
    1.88 +   * @param failureCb
    1.89 +   *        Error callback to call when an error is encountered.
    1.90 +   */
    1.91 +  ensureDB: function ensureDB(aSuccessCb, aFailureCb) {
    1.92 +    if (this._db) {
    1.93 +      if (DEBUG) debug("ensureDB: already have a database, returning early.");
    1.94 +      aSuccessCb && aSuccessCb();
    1.95 +      return;
    1.96 +    }
    1.97 +    this.open(aSuccessCb, aFailureCb);
    1.98 +  },
    1.99 +
   1.100 +  /**
   1.101 +   * Start a new transaction.
   1.102 +   *
   1.103 +   * @param txn_type
   1.104 +   *        Type of transaction (e.g. "readwrite")
   1.105 +   * @param store_name
   1.106 +   *        The object store you want to be passed to the callback
   1.107 +   * @param callback
   1.108 +   *        Function to call when the transaction is available. It will
   1.109 +   *        be invoked with the transaction and the `store' object store.
   1.110 +   * @param successCb
   1.111 +   *        Success callback to call on a successful transaction commit.
   1.112 +   *        The result is stored in txn.result.
   1.113 +   * @param failureCb
   1.114 +   *        Error callback to call when an error is encountered.
   1.115 +   */
   1.116 +  newTxn: function newTxn(txn_type, store_name, callback, successCb, failureCb) {
   1.117 +    this.ensureDB(function () {
   1.118 +      if (DEBUG) debug("Starting new transaction" + txn_type);
   1.119 +      let txn = this._db.transaction(Array.isArray(store_name) ? store_name : this.dbStoreNames, txn_type);
   1.120 +      if (DEBUG) debug("Retrieving object store", this.dbName);
   1.121 +      let stores;
   1.122 +      if (Array.isArray(store_name)) {
   1.123 +        stores = [];
   1.124 +        for (let i = 0; i < store_name.length; ++i) {
   1.125 +          stores.push(txn.objectStore(store_name[i]));
   1.126 +        }
   1.127 +      } else {
   1.128 +        stores = txn.objectStore(store_name);
   1.129 +      }
   1.130 +
   1.131 +      txn.oncomplete = function (event) {
   1.132 +        if (DEBUG) debug("Transaction complete. Returning to callback.");
   1.133 +        if (successCb) {
   1.134 +          successCb(txn.result);
   1.135 +        }
   1.136 +      };
   1.137 +
   1.138 +      txn.onabort = function (event) {
   1.139 +        if (DEBUG) debug("Caught error on transaction");
   1.140 +        /*
   1.141 +         * event.target.error may be null
   1.142 +         * if txn was aborted by calling txn.abort()
   1.143 +         */
   1.144 +        if (failureCb) {
   1.145 +          if (event.target.error) {
   1.146 +            failureCb(event.target.error.name);
   1.147 +          } else {
   1.148 +            failureCb("UnknownError");
   1.149 +          }
   1.150 +        }
   1.151 +      };
   1.152 +      callback(txn, stores);
   1.153 +    }.bind(this), failureCb);
   1.154 +  },
   1.155 +
   1.156 +  /**
   1.157 +   * Initialize the DB. Does not call open.
   1.158 +   *
   1.159 +   * @param aDBName
   1.160 +   *        DB name for the open call.
   1.161 +   * @param aDBVersion
   1.162 +   *        Current DB version. User has to implement upgradeSchema.
   1.163 +   * @param aDBStoreName
   1.164 +   *        ObjectStore that is used.
   1.165 +   */
   1.166 +  initDBHelper: function initDBHelper(aDBName, aDBVersion, aDBStoreNames) {
   1.167 +    this.dbName = aDBName;
   1.168 +    this.dbVersion = aDBVersion;
   1.169 +    this.dbStoreNames = aDBStoreNames;
   1.170 +  }
   1.171 +}

mercurial