blob: 42ba6b6375133b66dc5a422a309d28b2048a9e7f [file] [log] [blame]
/*
* Copyright 2011 Google Inc.
*
* 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.
*/
package com.google.gwt.storage.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.PartialSupport;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* Implements the HTML5 Storage interface.
*
* <p>
* You can obtain a Storage by either invoking
* {@link #getLocalStorageIfSupported()} or
* {@link #getSessionStorageIfSupported()}.
* </p>
*
* <p>
* <span style="color:red">Experimental API: This API is still under development
* and is subject to change. </span>
* </p>
*
* <p>
* If Web Storage is NOT supported in the browser, these methods return <code>
* null</code>.
* </p>
*
* <p>
* Note: Storage events into other windows are not supported.
* </p>
*
*
* <p>
* This may not be supported on all browsers.
* </p>
*
* @see <a href="http://www.w3.org/TR/webstorage/#storage-0">W3C Web Storage -
* Storage</a>
* @see <a
* href="http://devworld.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Name-ValueStorage/Name-ValueStorage.html">Safari
* Client-Side Storage and Offline Applications Programming Guide -
* Key-Value Storage</a>
* @see <a href="http://quirksmode.org/dom/html5.html#t00">Quirksmode.org -
* HTML5 Compatibility - Storage</a>
* @see <a href="http://code.google.com/p/gwt-mobile-webkit/wiki/StorageApi">Wiki - Quickstart Guide</a>
*/
// TODO(pdr): Add support for Object values, instead of just Strings. The
// Storage API spec specifies this, but browser support poor at the moment.
// TODO(pdr): Add support for native events once browsers correctly implement
// storage events.
@PartialSupport
public final class Storage {
// Still a separate class to prevent native calls on class load as it my break existing code.
private static class StorageSupportDetector {
static final boolean localStorageSupported = checkStorageSupport(StorageImpl.LOCAL_STORAGE);
static final boolean sessionStorageSupported = checkStorageSupport(StorageImpl.SESSION_STORAGE);
// Adapted from modernizr
private static native boolean checkStorageSupport(String storage) /*-{
var c = '_gwt_dummy_';
try {
$wnd[storage].setItem(c, c);
$wnd[storage].removeItem(c);
return true;
} catch (e) {
return false;
}
}-*/;
}
static final StorageImpl impl = GWT.create(StorageImpl.class);
private static Storage localStorage;
private static Storage sessionStorage;
/**
* Registers an event handler for StorageEvents.
*
* @see <a href="http://www.w3.org/TR/webstorage/#the-storage-event">W3C Web
* Storage - the storage event</a>
* @param handler
* @return {@link HandlerRegistration} used to remove this handler
*/
public static HandlerRegistration addStorageEventHandler(
StorageEvent.Handler handler) {
return impl.addStorageEventHandler(handler);
}
/**
* Returns a Local Storage.
*
* <p>
* The returned storage is associated with the <a
* href="http://www.w3.org/TR/html5/browsers.html#origin">origin</a> of the
* Document.
* </p>
*
* @see <a href="http://www.w3.org/TR/webstorage/#dom-localstorage">W3C Web
* Storage - localStorage</a>
* @return the localStorage instance, or <code>null</code> if Web Storage is
* NOT supported.
*/
public static Storage getLocalStorageIfSupported() {
if (localStorage == null && isLocalStorageSupported()) {
localStorage = new Storage(StorageImpl.LOCAL_STORAGE);
}
return localStorage;
}
/**
* Returns a Session Storage.
*
* <p>
* The returned storage is associated with the current <a href=
* "http://www.w3.org/TR/html5/browsers.html#top-level-browsing-context"
* >top-level browsing context</a>.
* </p>
*
* @see <a href="http://www.w3.org/TR/webstorage/#dom-sessionstorage">W3C Web
* Storage - sessionStorage</a>
* @return the sessionStorage instance, or <code>null</code> if Web Storage is
* NOT supported.
*/
public static Storage getSessionStorageIfSupported() {
if (sessionStorage == null && isSessionStorageSupported()) {
sessionStorage = new Storage(StorageImpl.SESSION_STORAGE);
}
return sessionStorage;
}
/**
* Returns <code>true</code> if the <code>localStorage</code> part of the
* Storage API is supported on the running platform.
*/
public static boolean isLocalStorageSupported() {
return StorageSupportDetector.localStorageSupported;
}
/**
* Returns <code>true</code> if the <code>sessionStorage</code> part of the
* Storage API is supported on the running platform.
*/
public static boolean isSessionStorageSupported() {
return StorageSupportDetector.sessionStorageSupported;
}
/**
* Returns <code>true</code> if the Storage API (both localStorage and
* sessionStorage) is supported on the running platform.
*/
public static boolean isSupported() {
return isLocalStorageSupported() && isSessionStorageSupported();
}
/**
* De-registers an event handler for StorageEvents.
*
* @see <a href="http://www.w3.org/TR/webstorage/#the-storage-event">W3C Web
* Storage - the storage event</a>
* @param handler
*/
public static void removeStorageEventHandler(StorageEvent.Handler handler) {
impl.removeStorageEventHandler(handler);
}
// Contains either "localStorage" or "sessionStorage":
private final String storage;
/**
* This class can never be instantiated externally. Use
* {@link #getLocalStorageIfSupported()} or
* {@link #getSessionStorageIfSupported()} instead.
*/
private Storage(String storage) {
this.storage = storage;
}
/**
* Removes all items in the Storage.
*
* @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-clear">W3C Web
* Storage - Storage.clear()</a>
*/
public void clear() {
impl.clear(storage);
}
/**
* Returns the item in the Storage associated with the specified key.
*
* @param key the key to a value in the Storage
* @return the value associated with the given key
* @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-getitem">W3C Web
* Storage - Storage.getItem(k)</a>
*/
public String getItem(String key) {
return impl.getItem(storage, key);
}
/**
* Returns the number of items in this Storage.
*
* @return number of items in this Storage
* @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-l">W3C Web
* Storage - Storage.length()</a>
*/
public int getLength() {
return impl.getLength(storage);
}
/**
* Returns the key at the specified index.
*
* @param index the index of the key
* @return the key at the specified index in this Storage
* @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-key">W3C Web
* Storage - Storage.key(n)</a>
*/
public String key(int index) {
return impl.key(storage, index);
}
/**
* Removes the item in the Storage associated with the specified key.
*
* @param key the key to a value in the Storage
* @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-removeitem">W3C
* Web Storage - Storage.removeItem(k)</a>
*/
public void removeItem(String key) {
impl.removeItem(storage, key);
}
/**
* Sets the value in the Storage associated with the specified key to the
* specified data.
*
* Note: The empty string may not be used as a key.
*
* @param key the key to a value in the Storage
* @param data the value associated with the key
* @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-setitem">W3C Web
* Storage - Storage.setItem(k,v)</a>
*/
public void setItem(String key, String data) {
// prevent the empty string due to a Firefox bug:
// bugzilla.mozilla.org/show_bug.cgi?id=510849
assert key.length() > 0;
impl.setItem(storage, key, data);
}
}