indexeddb.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // Copyright 2011 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Wrapper for an IndexedDB database.
  16. *
  17. */
  18. goog.provide('goog.db.IndexedDb');
  19. goog.require('goog.db.Error');
  20. goog.require('goog.db.ObjectStore');
  21. goog.require('goog.db.Transaction');
  22. goog.require('goog.events.Event');
  23. goog.require('goog.events.EventHandler');
  24. goog.require('goog.events.EventTarget');
  25. /**
  26. * Creates an IDBDatabase wrapper object. The database object has methods for
  27. * setting the version to change the structure of the database and for creating
  28. * transactions to get or modify the stored records. Should not be created
  29. * directly, call {@link goog.db.openDatabase} to set up the connection.
  30. *
  31. * @param {!IDBDatabase} db Underlying IndexedDB database object.
  32. * @constructor
  33. * @extends {goog.events.EventTarget}
  34. * @final
  35. */
  36. goog.db.IndexedDb = function(db) {
  37. goog.db.IndexedDb.base(this, 'constructor');
  38. /**
  39. * Underlying IndexedDB database object.
  40. *
  41. * @type {!IDBDatabase}
  42. * @private
  43. */
  44. this.db_ = db;
  45. /**
  46. * Internal event handler that listens to IDBDatabase events.
  47. * @type {!goog.events.EventHandler<!goog.db.IndexedDb>}
  48. * @private
  49. */
  50. this.eventHandler_ = new goog.events.EventHandler(this);
  51. this.eventHandler_.listen(
  52. this.db_, goog.db.IndexedDb.EventType.ABORT,
  53. goog.bind(this.dispatchEvent, this, goog.db.IndexedDb.EventType.ABORT));
  54. this.eventHandler_.listen(
  55. this.db_, goog.db.IndexedDb.EventType.ERROR, this.dispatchError_);
  56. this.eventHandler_.listen(
  57. this.db_, goog.db.IndexedDb.EventType.VERSION_CHANGE,
  58. this.dispatchVersionChange_);
  59. this.eventHandler_.listen(
  60. this.db_, goog.db.IndexedDb.EventType.CLOSE,
  61. goog.bind(this.dispatchEvent, this, goog.db.IndexedDb.EventType.CLOSE));
  62. };
  63. goog.inherits(goog.db.IndexedDb, goog.events.EventTarget);
  64. /**
  65. * True iff the database connection is open.
  66. *
  67. * @type {boolean}
  68. * @private
  69. */
  70. goog.db.IndexedDb.prototype.open_ = true;
  71. /**
  72. * Dispatches a wrapped error event based on the given event.
  73. *
  74. * @param {Event} ev The error event given to the underlying IDBDatabase.
  75. * @private
  76. */
  77. goog.db.IndexedDb.prototype.dispatchError_ = function(ev) {
  78. this.dispatchEvent({
  79. type: goog.db.IndexedDb.EventType.ERROR,
  80. errorCode: /** @type {IDBRequest} */ (ev.target).error.severity
  81. });
  82. };
  83. /**
  84. * Dispatches a wrapped version change event based on the given event.
  85. *
  86. * @param {Event} ev The version change event given to the underlying
  87. * IDBDatabase.
  88. * @private
  89. */
  90. goog.db.IndexedDb.prototype.dispatchVersionChange_ = function(ev) {
  91. this.dispatchEvent(
  92. new goog.db.IndexedDb.VersionChangeEvent(ev.oldVersion, ev.newVersion));
  93. };
  94. /**
  95. * Closes the database connection. Metadata queries can still be made after this
  96. * method is called, but otherwise this wrapper should not be used further.
  97. */
  98. goog.db.IndexedDb.prototype.close = function() {
  99. if (this.open_) {
  100. this.db_.close();
  101. this.open_ = false;
  102. }
  103. };
  104. /**
  105. * @return {boolean} Whether a connection is open and the database can be used.
  106. */
  107. goog.db.IndexedDb.prototype.isOpen = function() {
  108. return this.open_;
  109. };
  110. /**
  111. * @return {string} The name of this database.
  112. */
  113. goog.db.IndexedDb.prototype.getName = function() {
  114. return this.db_.name;
  115. };
  116. /**
  117. * @return {number} The current database version.
  118. */
  119. goog.db.IndexedDb.prototype.getVersion = function() {
  120. // TODO(bradfordcsmith): drop Number() call once closure compiler's externs
  121. // are updated
  122. return Number(this.db_.version);
  123. };
  124. /**
  125. * @return {DOMStringList} List of object stores in this database.
  126. */
  127. goog.db.IndexedDb.prototype.getObjectStoreNames = function() {
  128. return this.db_.objectStoreNames;
  129. };
  130. /**
  131. * Creates an object store in this database. Can only be called inside a
  132. * {@link goog.db.UpgradeNeededCallback}.
  133. *
  134. * @param {string} name Name for the new object store.
  135. * @param {!IDBObjectStoreParameters=} opt_params Options object.
  136. * The available options are:
  137. * keyPath, which is a string and determines what object attribute
  138. * to use as the key when storing objects in this object store; and
  139. * autoIncrement, which is a boolean, which defaults to false and determines
  140. * whether the object store should automatically generate keys for stored
  141. * objects. If keyPath is not provided and autoIncrement is false, then all
  142. * insert operations must provide a key as a parameter.
  143. * @return {!goog.db.ObjectStore} The newly created object store.
  144. * @throws {goog.db.Error} If there's a problem creating the object store.
  145. */
  146. goog.db.IndexedDb.prototype.createObjectStore = function(name, opt_params) {
  147. try {
  148. return new goog.db.ObjectStore(
  149. this.db_.createObjectStore(name, opt_params));
  150. } catch (ex) {
  151. throw goog.db.Error.fromException(ex, 'creating object store ' + name);
  152. }
  153. };
  154. /**
  155. * Deletes an object store. Can only be called inside a
  156. * {@link goog.db.UpgradeNeededCallback}.
  157. *
  158. * @param {string} name Name of the object store to delete.
  159. * @throws {goog.db.Error} If there's a problem deleting the object store.
  160. */
  161. goog.db.IndexedDb.prototype.deleteObjectStore = function(name) {
  162. try {
  163. this.db_.deleteObjectStore(name);
  164. } catch (ex) {
  165. throw goog.db.Error.fromException(ex, 'deleting object store ' + name);
  166. }
  167. };
  168. /**
  169. * Creates a new transaction.
  170. *
  171. * @param {!Array<string>} storeNames A list of strings that contains the
  172. * transaction's scope, the object stores that this transaction can operate
  173. * on.
  174. * @param {goog.db.Transaction.TransactionMode=} opt_mode The mode of the
  175. * transaction. If not present, the default is READ_ONLY.
  176. * @return {!goog.db.Transaction} The wrapper for the newly created transaction.
  177. * @throws {goog.db.Error} If there's a problem creating the transaction.
  178. */
  179. goog.db.IndexedDb.prototype.createTransaction = function(storeNames, opt_mode) {
  180. try {
  181. // IndexedDB on Chrome 22+ requires that opt_mode not be passed rather than
  182. // be explicitly passed as undefined.
  183. var transaction = opt_mode ? this.db_.transaction(storeNames, opt_mode) :
  184. this.db_.transaction(storeNames);
  185. return new goog.db.Transaction(transaction, this);
  186. } catch (ex) {
  187. throw goog.db.Error.fromException(ex, 'creating transaction');
  188. }
  189. };
  190. /** @override */
  191. goog.db.IndexedDb.prototype.disposeInternal = function() {
  192. goog.db.IndexedDb.base(this, 'disposeInternal');
  193. this.eventHandler_.dispose();
  194. };
  195. /**
  196. * Event types fired by a database.
  197. *
  198. * @enum {string} The event types for the web socket.
  199. */
  200. goog.db.IndexedDb.EventType = {
  201. /**
  202. * Fired when a transaction is aborted and the event bubbles to its database.
  203. */
  204. ABORT: 'abort',
  205. /**
  206. * Fired when the database connection is forcibly closed by the browser,
  207. * without an explicit call to IDBDatabase#close. This behavior is not in the
  208. * spec yet but will be added since it is necessary, see
  209. * https://www.w3.org/Bugs/Public/show_bug.cgi?id=22540.
  210. */
  211. CLOSE: 'close',
  212. /**
  213. * Fired when a transaction has an error.
  214. */
  215. ERROR: 'error',
  216. /**
  217. * Fired when someone (possibly in another window) is attempting to modify the
  218. * structure of the database. Since a change can only be made when there are
  219. * no active database connections, this usually means that the database should
  220. * be closed so that the other client can make its changes.
  221. */
  222. VERSION_CHANGE: 'versionchange'
  223. };
  224. /**
  225. * Event representing a (possibly attempted) change in the database structure.
  226. *
  227. * At time of writing, no Chrome versions support oldVersion or newVersion. See
  228. * http://crbug.com/153122.
  229. *
  230. * @param {number} oldVersion The previous version of the database.
  231. * @param {number} newVersion The version the database is being or has been
  232. * updated to.
  233. * @constructor
  234. * @extends {goog.events.Event}
  235. * @final
  236. */
  237. goog.db.IndexedDb.VersionChangeEvent = function(oldVersion, newVersion) {
  238. goog.db.IndexedDb.VersionChangeEvent.base(
  239. this, 'constructor', goog.db.IndexedDb.EventType.VERSION_CHANGE);
  240. /**
  241. * The previous version of the database.
  242. * @type {number}
  243. */
  244. this.oldVersion = oldVersion;
  245. /**
  246. * The version the database is being or has been updated to.
  247. * @type {number}
  248. */
  249. this.newVersion = newVersion;
  250. };
  251. goog.inherits(goog.db.IndexedDb.VersionChangeEvent, goog.events.Event);