Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML5

HTML5 Web Storage in Essence

4.90/5 (55 votes)
15 Apr 2012CPOL11 min read 188.2K   1.3K  
Web Storage is a brand new mechanism of storing HTTP state data, which was introduced in HTML5 to replace cookie. I delve deep into its client store mechanism and advantages compare to cookie, at the mean time I describe how JavaScript can manipulate it and also how browsers store localStorage.

Background

Web Storage (also named DOM Storage) brought in two brand new objects: sessionStorage and localStorage. In Web Storage Spec, Ian Hickson documented that Web Storage is intended to solve two cases that are "not handled well by Cookies". They are:

  1. The first is designed for scenarios where the user is carrying out a single transaction, but could be carrying out multiple transactions in different windows at the same time.
  2. The second storage mechanism is designed for storage that spans multiple windows, and lasts beyond the current session. In particular, Web applications may wish to store megabytes of user data, such as entire user-authored documents or a user's mailbox, on the client side for performance reasons.

sessionStorage and localStorage are introduced by W3 in HTML5 to solve problems above, let's begin with a review of how Cookie currently works.

Current HTTP State Storage – Cookie

Mechanism

An HTTP Cookie was a set of key / value pairs which an HTTP web server requests a concrete client browser (i.e. User Agent - UA) to store on client's hard disk, when the UA request to the web server further, UA will wrap all the cookie data within the HTTP request header as long as following conditions are all satisfied:

  1. The cookie data has not expired.
  2. The requested domain is under exactly the same domain when cookie was stored.
  3. The requested path under the domain is the same one where cookie was stored.

Once the cookie expires, browser will delete it from local hard disk.

A common cookie example:

  1. An end user types www.foo.net in a browser's navigation bar and hits enter.
  2. www.foo.net returns HTTP status 200 message below (In the Green part, web server expected client browser to store two Cookie key/value pairs: WayneKey1=value1; WayneKey2=Value2, they could be accessible from the entire domain, and they will expire after 1 year):

    HTTP/1.1 200 OK 
    Content-type: text/html 
    <span style="color: green; ">Set-Cookie: WayneKey1=value1;WayneKey2=Value2;domain=www.foo.net; 
    expires=Tue, 24-Feb-2012 07:13:22 GMT; path=/; HttpOnly</span> 
    
    
    (Response HTTP body)
  3. Browser received the HTTP response and stored the cookie key/values in plain text into user's hard disk.

  4. User did some interactions and requested back www.foo.net, browser will wrap the cookie data into request HTTP header.

    GET /Index.aspx HTTP 1.1 
    HOST: <a href="http://www.foo.net/">www.foo.net</a> 
    Accept: *.* 
    <span style="color: green; ">Cookie: WayneKey1=value1;WayneKey2=Value2;</span> 
    
    (Request HTTP body)

Notes: In #4 above, if client browser does not support cookie or cookie is disabled by user, a fallback mechanism might be implemented by the HTTP Web server, which can usually store cookie data within the URL (for an instance example, ASP.NET can support storing cookie in URL by setting cookieless="UseUri" in web.config, refer: Cookieless ASP.NET), or alternatively, the Web server won't allow client to use its features.

Based on a server allocated Session ID storing in client cookie, Session object is widely used in all popular web servers to store temporary data on server side (could be memory, database or a dedicated session storage server and so on), in case client disabled cookie, web server might adopt the same strategy mentioned above (storing cookie in URL), or instead, they do not allow client to use its features except client gets cookie enabled.

Situation

Nowadays countless websites (for example Google, Facebook, Amazon, New York Times) rely on HTTP cookie to store data such as user preference, login information, shopping cart and so on. If you disable cookie in your browser and try to access many extremely popular web applications (like Facebook, Twitter, Gmail, Amazon and so on) today, you probably see screenshots below:

Web-Storage-In-Essence/GoogleNoCookie.jpg

Image 2

Image 3

In one word, cookie enabled is a mandatory condition to use these web giants.

Cookie Drawbacks

I investigated and summarized a number of drawbacks of Cookie listed below (two W3C points mentioned at the beginning are included):

  • Size and count limit
    Most browsers limited cookie size to 4096 bytes and 300 maximum cookie count within a domain. IETF recommended limitation standard, refer: http://www.ietf.org/rfc/rfc2109.txt section 6.3.
  • Performance hit
    If a website uses cookie, then every HTTP request/response between server / browser must include all cookie key / values pairs in the HTTP header.
  • Security
    Cookie is stored in user's local hard disk in plaint text. If developers didn't deal with this appropriately, cookie/session hijacking could possibly happen.
  • Ability to store data separately for more than one instance of same web application
    Cookie is not easy to handle one use case: separate instances of the same web application to run in different windows without interfering with each other (sessionStorage is going to well-support that, I will describe it later in this post).

Web Storage Mechanism

Unlike cookie which passed between server/client and could be accessed by both of them, sessionStorage / localStorage are 100% stored in the client by a concrete browser, sessionStorage temporarily stores data in one HTTP session, localStorage stores permanent data into client hard disk. The advantage is obvious:

  • Data won't be passed through HTTP request/response, bandwidth will be saved.
  • There will be no 4KB limitation, web site has much more flexibility to store large data in client.
    Notes: W3C "recommended 5 megabytes localStorage size limitation per domain", and "welcome feedback", this is much larger than 4KB limitation in cookie.
  • Now that data won't be passed through network, this will be relatively more secure.
  • Considering further according to #3, a number of existing HTTPs connection in theory could use plain HTTP by adopting Web Storage, because there is no need to encrypt the data, the data is stored in client side. Since HTTPs usually have only 10% performance comparing with HTTP, eventually either performance will be improved or cost is saved (procuring cheaper server hardware).

In my humble opinion, Web Storage is one the greatest features in HTML5, and I believe it will lead an HTTP web state storage revolution in the near future! Why? Considering several stories listed below, I guess they will very possibly happen soon!

  1. Bandwidth save. You have an Email account of a popular Email service web application, and you use it daily, at very first time of your visit in a concrete browser. It stores your 300+ contacts list as well as your newest 20 email threads (first page) into your browser's local storage, and the data takes approximate 8 kilobytes in total. In future visits, this 8 kilobytes will not be transferred from the Email server.
  2. No download time = Better UX. You like watching videos from a popular video web site, which records video list (by default 10 latest watched videos) you've watched as well as indexed real video stream data. Every time you visit the web site, you have an ability to view your watching history and most important, you can re-watch any video in the list in a second – from your local storage.
  3. Surfing same web sites using more than one account simultaneously. For some reason, you registered two accounts in one web site, which uses session storage, and you can login with these two account in two browser tabs and interactive in isolation. For example, checking Gmail in two Tabs using two Gmail account at the same time.

Manipulating Storage in JavaScript

The Storage Interface

Both sessionStorage / localStorage are inherited from an interface Storage, it defined in Web Storage Spec:

C#
interface Storage {
  readonly attribute unsigned long length;
  DOMString key(in unsigned long index);
  getter any getItem(in DOMString key);
  setter creator void setItem(in DOMString key, in any value);
  deleter void removeItem(in DOMString key);
  void clear();
};

Basic Operations

First things first, we need to check whether a concrete browser supports Web Storage or not, per Wikipedia: Comparison of layout engines (HTML5), IE8+ (IE8 does NOT support Storage Event, while IE9 RC supports), Firefox 3.5+, Safari 4.0+, Chrome 4.0+ all support Web Storage. We can write a simple JS function to check whether client browser supports Web Storage or not:

JavaScript
function supportsLocalStorage() {
    return ('localStorage' in window) && window['localStorage'] !== null;
}

if(supportsLocalStorage()) {
    // Web Storage invocation here
}
else {
    alert('Sorry, your browser does not support Web Storage');
}

If the browser does support, then invoking sessionStorage and localStorage in JavaScript is fairly easy. Sample code which demonstrates set / get / remove / clear items storage shows below:

JavaScript
// Set/Get locallStorage
localStorage.{key} = strValue;
var localVal = localStorage.{key};

// Set/Get sessionlStorage
sessionStorage.{key} = strValue;
var sessionVal = sessionStorage.{key};

// Remove an storage item
localStorage.removeItem('key')
sessionStorage.removeItem('key')

// Clear storage
localStorage.clear();
sessionStorage.clear();

Please be aware of one thing: both sessionStorage and localStorage can only store DOM string value, what if we want to store JavaScript object into them, the answer is definitely JSON string, and someone at StackOverFlow has provided an elegant way to extend Storage.setObject / getObject method by using JavaScript prototype, code shows below:

C#
Storage.prototype.setObject = function (key, value) {
    this.setItem(key, JSON.stringify(value));
}
 
Storage.prototype.getObject = function (key) {
    return this.getItem(key) && JSON.parse(this.getItem(key));
}
 
// By extending Storage's prototype above, just simply add/get 
// JavaScript object into Storage
localStorage.setObject('key',objValue);
localStorage.getObject('key',objValue);
sessionStorage.setObject('key', objValue);
sessionStorage.getObject('key', objValue);

My attached WebStorageDemo shows how to store both DOM String and JSON String into sessionStorage / localStorage, code snippet and screenshot showing below:

Store several fake Shopping Cart items into sessionStorage:

JavaScript
function S4() {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
function Guid() {
    return (S4() + S4() + "-" + S4() + "-" + S4() + 
	"-" + S4() + "-" + S4() + S4() + S4());
}
function ShoppingCartItem() {
    this.ProductID = Guid();
    this.ProductName = '';
    this.CategoryID = -1;
    this.Price = -1.0;
}

// Fake items in shopping cart, and store into sessionStorage
var item1 = new ShoppingCartItem();
item1.ProductName = 'HP WebOS Topaz';
item1.CategoryID = 8;
item1.Price = 849.99;
var item2 = new ShoppingCartItem();
item2.ProductName = 'Apple Ipad II';
item2.CategoryID = 10;
item2.Price = 799.99;

var currentUserShoppingCart = new Array();
currentUserShoppingCart[0] = item1;
currentUserShoppingCart[1] = item2;
sessionStorage.setObject('UserShoppingCart', currentUserShoppingCart);

Image 4

Delve Deep into sessionStorage / localStorage Mechanism

As I mentioned at the beginning, both sessionStorage /localStorage are "100% stored in the client by a concrete browser", the difference between them is that sessionStorage is window/tab isolated while localStorage is shared across pages under a domain, in other words, sessionStorage takes care of storing temporary data during an HTTP session life time happened in one browser window/tab, each window/tab can maintain its own session data; While localStorage stores data persists into user's hard disk, all pages under this concrete domain can manipulate the localStorage.

Let's again see a demo, I added a Counter which stored natural number into sessionStorage, and a clickable button can increase the Counter, code below:

HTML
<input type="button" value="Counter++"  önclick="sessionStorage.Counter++;" />

And I open two instances of the page, respectively click Counter++ on each page, then we will see each of them keeps its own counter:

Image 5

On the contrary, data stored in localStorage could be accessed by all pages under the same domain, in the demo shown below, initially I inserted a fake UserProfile into localStorage, and then open another page which has different path but under the same domain, we will see UserProfile stored by first page can be retrieved.

Image 6

Notes: Now that localStorage is shared, it therefore might be manipulated by more than one page simultaneously, W3 emphasized that the browser should implement Storage mutex to ensure the Thread safe of localStorage.

By achieving these mechanisms, sessionStorage / localStorage is supposed to replace Cookie with a more straight-forward, effective and secure manner.

Storage Event

W3 defines StorageEvent interface as below:

C#
interface StorageEvent : Event {
  readonly attribute DOMString key;
  readonly attribute any oldValue;
  readonly attribute any newValue;
  readonly attribute DOMString url;
  readonly attribute Storage storageArea;
  void initStorageEvent(in DOMString typeArg, in boolean canBubbleArg, 
	in boolean cancelableArg, in DOMString keyArg, in any oldValueArg, 
	in any newValueArg, in DOMString urlArg, in Storage storageAreaArg);
};

Most famous browser (latest version) have implemented StorageEvent, see screenshot below below: 

Image 7

However, by my observation, the implementations between IE 9 and Gecko/Webkit are slightly different, the Storage Event demo on HTML5Demos hinted that the event will only be caught in the other window/tab, but if you are using IE 9 you will see it actually can be fired. 

So the situation is:

  • Gecko/Webkit: StorageEvent gets fired only in different window/tab against the window/tab which changed the storage key. In additional,  value changes on an existing key won't trigger the event!  
  • IE 9:   StorageEvent gets fired in ALL windows/tabs, and also gets fired when value changes. 

I use IE 9 to do the demo below just for convenience. The GIF below demonstrates that when I insert a new object into localStorage, onStorageChanged function was triggered on two page instances simultaneously, and displays the new inserted data at the same time:

Image 8

Notes: Since data stored in localStorage can be accessed by all page instances under a domain, those page instances can monitor the change (StorageEvent) simultaneously, we can achieve "passing data crossing pages at the very same time" which was not easy to do before HTML5 (another way to achieve this is WebMessaging but it is more supposed to do Cross-Domain communication). 

Storage Location/Format 

Let's delve to one deeper level, how browsers store localStorage: the location and data format. I observed IE9 and Google Chrome on Windows 7, and my conclusion is summarized in the table below:

BrowserlocalStorage locationData Format
IE 9 RC%userprofile%\AppData\Local\Microsoft\Internet Explorer\DOMStore\Plaint XML
Chrome%userprofile%\AppData\Local\Google\Chrome\User Data\Default\Local StorageSQLite

IE 9 actually stores localStorage items a simple XML file, below is how the XML stores UserProfile object in my demo:

XML
<root>
    <item 
    name="UserProfile" 
    value="{&quot;NickName&quot;:&quot;Wayne&quot;,&quot;EmailAddress&quot;
    :&quot;WebMaster@WayneYe.com&quot;}"
    ltime="3439488560" 
    htime="30135140" />
</root>

Chrome stores data in a SQLite simple database table with two columns: Key and Value, screenshot below:

Image 9

Demo Code Notes 

Please download WebStorageDemo.zip including all my sample code above, I've also put the compete demo on to my blog: http://WayneYe.com/Demo/HTML5/WebStorageDemo.htm.

Please note if you test my attached demo or try any code related with Web Storage in IE 9, please make sure you added X-UA-Capability meta information in your HTML header, or explicitly set both Browse mode/Document mode to Internet Explorer 9 Standards in IE Developer tool, otherwise you probably see JS errors since IE 6,7 does NOT recognize sessionStorage / localStorage.

XML
<meta http-equiv="X-UA-Compatible" content="IE=9" />

Image 10

Conclusion

Compared to HTTP Cookie, HTML5 Web Storage mechanism provides relatively more convenient, flexible, secure and faster way to store HTTP state data, it should replace HTTP Cookie gradually, especially nowadays most of the popular web browsers support it (although there might be several issues such as StorageEvent I mentioned above), they do conform to the W3C standard to store data in sessionStorage / localStorage. Ian Hickson "expected HTML 5 becomes Candidate Recommendation stage during 2012", let's be expecting and excited to see how things are going in the coming future.

Further Reading

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)