html5webstorage.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 Base class that implements functionality common
  16. * across both session and local web storage mechanisms.
  17. *
  18. */
  19. goog.provide('goog.storage.mechanism.HTML5WebStorage');
  20. goog.require('goog.asserts');
  21. goog.require('goog.iter.Iterator');
  22. goog.require('goog.iter.StopIteration');
  23. goog.require('goog.storage.mechanism.ErrorCode');
  24. goog.require('goog.storage.mechanism.IterableMechanism');
  25. /**
  26. * Provides a storage mechanism that uses HTML5 Web storage.
  27. *
  28. * @param {Storage} storage The Web storage object.
  29. * @constructor
  30. * @struct
  31. * @extends {goog.storage.mechanism.IterableMechanism}
  32. */
  33. goog.storage.mechanism.HTML5WebStorage = function(storage) {
  34. goog.storage.mechanism.HTML5WebStorage.base(this, 'constructor');
  35. /**
  36. * The web storage object (window.localStorage or window.sessionStorage).
  37. * @private {Storage}
  38. */
  39. this.storage_ = storage;
  40. };
  41. goog.inherits(
  42. goog.storage.mechanism.HTML5WebStorage,
  43. goog.storage.mechanism.IterableMechanism);
  44. /**
  45. * The key used to check if the storage instance is available.
  46. * @private {string}
  47. * @const
  48. */
  49. goog.storage.mechanism.HTML5WebStorage.STORAGE_AVAILABLE_KEY_ = '__sak';
  50. /**
  51. * Determines whether or not the mechanism is available.
  52. * It works only if the provided web storage object exists and is enabled.
  53. *
  54. * @return {boolean} True if the mechanism is available.
  55. */
  56. goog.storage.mechanism.HTML5WebStorage.prototype.isAvailable = function() {
  57. if (!this.storage_) {
  58. return false;
  59. }
  60. try {
  61. // setItem will throw an exception if we cannot access WebStorage (e.g.,
  62. // Safari in private mode).
  63. this.storage_.setItem(
  64. goog.storage.mechanism.HTML5WebStorage.STORAGE_AVAILABLE_KEY_, '1');
  65. this.storage_.removeItem(
  66. goog.storage.mechanism.HTML5WebStorage.STORAGE_AVAILABLE_KEY_);
  67. return true;
  68. } catch (e) {
  69. return false;
  70. }
  71. };
  72. /** @override */
  73. goog.storage.mechanism.HTML5WebStorage.prototype.set = function(key, value) {
  74. try {
  75. // May throw an exception if storage quota is exceeded.
  76. this.storage_.setItem(key, value);
  77. } catch (e) {
  78. // In Safari Private mode, conforming to the W3C spec, invoking
  79. // Storage.prototype.setItem will allways throw a QUOTA_EXCEEDED_ERR
  80. // exception. Since it's impossible to verify if we're in private browsing
  81. // mode, we throw a different exception if the storage is empty.
  82. if (this.storage_.length == 0) {
  83. throw goog.storage.mechanism.ErrorCode.STORAGE_DISABLED;
  84. } else {
  85. throw goog.storage.mechanism.ErrorCode.QUOTA_EXCEEDED;
  86. }
  87. }
  88. };
  89. /** @override */
  90. goog.storage.mechanism.HTML5WebStorage.prototype.get = function(key) {
  91. // According to W3C specs, values can be of any type. Since we only save
  92. // strings, any other type is a storage error. If we returned nulls for
  93. // such keys, i.e., treated them as non-existent, this would lead to a
  94. // paradox where a key exists, but it does not when it is retrieved.
  95. // http://www.w3.org/TR/2009/WD-webstorage-20091029/#the-storage-interface
  96. var value = this.storage_.getItem(key);
  97. if (!goog.isString(value) && !goog.isNull(value)) {
  98. throw goog.storage.mechanism.ErrorCode.INVALID_VALUE;
  99. }
  100. return value;
  101. };
  102. /** @override */
  103. goog.storage.mechanism.HTML5WebStorage.prototype.remove = function(key) {
  104. this.storage_.removeItem(key);
  105. };
  106. /** @override */
  107. goog.storage.mechanism.HTML5WebStorage.prototype.getCount = function() {
  108. return this.storage_.length;
  109. };
  110. /** @override */
  111. goog.storage.mechanism.HTML5WebStorage.prototype.__iterator__ = function(
  112. opt_keys) {
  113. var i = 0;
  114. var storage = this.storage_;
  115. var newIter = new goog.iter.Iterator();
  116. newIter.next = function() {
  117. if (i >= storage.length) {
  118. throw goog.iter.StopIteration;
  119. }
  120. var key = goog.asserts.assertString(storage.key(i++));
  121. if (opt_keys) {
  122. return key;
  123. }
  124. var value = storage.getItem(key);
  125. // The value must exist and be a string, otherwise it is a storage error.
  126. if (!goog.isString(value)) {
  127. throw goog.storage.mechanism.ErrorCode.INVALID_VALUE;
  128. }
  129. return value;
  130. };
  131. return newIter;
  132. };
  133. /** @override */
  134. goog.storage.mechanism.HTML5WebStorage.prototype.clear = function() {
  135. this.storage_.clear();
  136. };
  137. /**
  138. * Gets the key for a given key index. If an index outside of
  139. * [0..this.getCount()) is specified, this function returns null.
  140. * @param {number} index A key index.
  141. * @return {?string} A storage key, or null if the specified index is out of
  142. * range.
  143. */
  144. goog.storage.mechanism.HTML5WebStorage.prototype.key = function(index) {
  145. return this.storage_.key(index);
  146. };