adds support for localStorage.  closes #21
diff --git a/weinre.web/demo/weinre-demo.css b/weinre.web/demo/weinre-demo.css
index ee3c64f..ec6d164 100644
--- a/weinre.web/demo/weinre-demo.css
+++ b/weinre.web/demo/weinre-demo.css
@@ -8,9 +8,9 @@
 h1 {
     color:         green;
     margin:        0.5em;
-    margin-right:  1.0em;
+    margin-left:   1.0em;
     padding:       0.4em;
-    padding-right: 0.8em;
+    padding-left : 0.8em;
 }
 
 .blue {
diff --git a/weinre.web/demo/weinre-demo.js b/weinre.web/demo/weinre-demo.js
index 5e3be85..6be2622 100644
--- a/weinre.web/demo/weinre-demo.js
+++ b/weinre.web/demo/weinre-demo.js
@@ -11,6 +11,7 @@
 var buttonStartStuff
 var buttonClearOutput
 var outputElement 
+var storageIndex = 0
 
 //------------------------------------------------------------------------------
 function onLoad() {
@@ -40,6 +41,11 @@
 var interval
 
 function startStuff() {
+    if (window.localStorage)   window.localStorage.clear()
+    if (window.sessionStorage) window.sessionStorage.clear()
+    
+    storageIndex = 0
+    
     interval = setInterval(intervalStuff, 1000)
 }
 
@@ -58,6 +64,18 @@
     // add a timeline marker
     console.markTimeline(message)
     
+    // write to local- and sessionStorage
+    if (window.localStorage) {
+        var smessage = message + " (local)"
+        window.localStorage.setItem(  "item-" + storageIndex, smessage)
+    }
+    
+    if (window.sessionStorage) {
+        var smessage = message + " (session)"
+        window.sessionStorage.setItem("item-" + storageIndex, smessage)
+    }
+    storageIndex++
+    
     // write the message to the page
     output(message)
     
diff --git a/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.scoop b/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.scoop
index c121a96..bb5093e 100644
--- a/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.scoop
+++ b/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.scoop
@@ -23,7 +23,8 @@
 
 //-----------------------------------------------------------------------------
 method hiddenPanels
-    return "audits,profiles,resources,network"
+//    return "audits,profiles,resources,network"
+    return "audits,profiles,network"
 //    return "audits,profiles,resources,scripts,timeline,network"
 
 //-----------------------------------------------------------------------------
diff --git a/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop b/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop
index c58fbb0..8c35aeb 100644
--- a/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop
+++ b/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop
@@ -54,6 +54,7 @@
     
     WebInspector.panels.elements.reset()
     WebInspector.panels.timeline._clearPanel()
+    WebInspector.panels.resources.reset()
 
 //-----------------------------------------------------------------------------
 method connectionDestroyed(/*int*/ clientId, /*int*/ targetId)
diff --git a/weinre.web/modules/weinre/common/Native.scoop b/weinre.web/modules/weinre/common/Native.scoop
index cc8ce08..705faa7 100644
--- a/weinre.web/modules/weinre/common/Native.scoop
+++ b/weinre.web/modules/weinre/common/Native.scoop
@@ -13,17 +13,28 @@
 init
     Native.original = {}
 
-    Native.original.clearInterval       = window.clearInterval
-    Native.original.clearTimeout        = window.clearTimeout
-    Native.original.setTimeout          = window.setTimeout
-    Native.original.setInterval         = window.setInterval
-    Native.original.XMLHttpRequest      = window.XMLHttpRequest
-    Native.original.XMLHttpRequest_open = window.XMLHttpRequest.prototype.open
+    Native.original.clearInterval             = window.clearInterval
+    Native.original.clearTimeout              = window.clearTimeout
+    Native.original.setTimeout                = window.setTimeout
+    Native.original.setInterval               = window.setInterval
+    Native.original.XMLHttpRequest            = window.XMLHttpRequest
+    Native.original.XMLHttpRequest_open       = window.XMLHttpRequest.prototype.open
+    Native.original.LocalStorage_setItem      = window.localStorage   ? window.localStorage.setItem      : null
+    Native.original.LocalStorage_removeItem   = window.localStorage   ? window.localStorage.removeItem   : null
+    Native.original.LocalStorage_clear        = window.localStorage   ? window.localStorage.clear        : null
+    Native.original.SessionStorage_setItem    = window.sessionStorage ? window.sessionStorage.setItem    : null
+    Native.original.SessionStorage_removeItem = window.sessionStorage ? window.sessionStorage.removeItem : null
+    Native.original.SessionStorage_clear      = window.sessionStorage ? window.sessionStorage.clear      : null
 
-    Native.clearInterval       = function() { return Native.original.clearInterval.apply( window, [].slice.call(arguments))}
-    Native.clearTimeout        = function() { return Native.original.clearTimeout.apply(  window, [].slice.call(arguments))}
-    Native.setInterval         = function() { return Native.original.setInterval.apply(   window, [].slice.call(arguments))}
-    Native.setTimeout          = function() { return Native.original.setTimeout.apply(    window, [].slice.call(arguments))}
-    Native.XMLHttpRequest      = function() { return new Native.original.XMLHttpRequest()}
-    Native.XMLHttpRequest_open = function() { return Native.original.XMLHttpRequest_open.apply(this, [].slice.call(arguments))}
-    
\ No newline at end of file
+    Native.clearInterval             = function() { return Native.original.clearInterval.apply( window, [].slice.call(arguments))}
+    Native.clearTimeout              = function() { return Native.original.clearTimeout.apply(  window, [].slice.call(arguments))}
+    Native.setInterval               = function() { return Native.original.setInterval.apply(   window, [].slice.call(arguments))}
+    Native.setTimeout                = function() { return Native.original.setTimeout.apply(    window, [].slice.call(arguments))}
+    Native.XMLHttpRequest            = function() { return new Native.original.XMLHttpRequest()}
+    Native.XMLHttpRequest_open       = function() { return Native.original.XMLHttpRequest_open.apply(this, [].slice.call(arguments))}
+    Native.LocalStorage_setItem      = function() { return Native.original.LocalStorage_setItem.apply(      window.localStorage,   [].slice.call(arguments))}
+    Native.LocalStorage_removeItem   = function() { return Native.original.LocalStorage_removeItem.apply(   window.localStorage,   [].slice.call(arguments))}
+    Native.LocalStorage_clear        = function() { return Native.original.LocalStorage_clear.apply(        window.localStorage,   [].slice.call(arguments))}
+    Native.SessionStorage_setItem    = function() { return Native.original.SessionStorage_setItem.apply(    window.sessionStorage, [].slice.call(arguments))}
+    Native.SessionStorage_removeItem = function() { return Native.original.SessionStorage_removeItem.apply( window.sessionStorage, [].slice.call(arguments))}
+    Native.SessionStorage_clear      = function() { return Native.original.SessionStorage_clear.apply(      window.sessionStorage, [].slice.call(arguments))}
diff --git a/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.scoop b/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.scoop
index 2a00e04..9adf1e9 100644
--- a/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.scoop
+++ b/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.scoop
@@ -25,6 +25,7 @@
 
     Weinre.target.setDocument()
     Weinre.wi.TimelineNotify.timelineProfilerWasStopped()
+    Weinre.wi.DOMStorage.initialize()
 
 //-----------------------------------------------------------------------------
 method connectionDestroyed(/*string*/ clientId, /*string*/ targetId)
diff --git a/weinre.web/modules/weinre/target/WiDOMStorageImpl.scoop b/weinre.web/modules/weinre/target/WiDOMStorageImpl.scoop
index cd42790..b3d907f 100644
--- a/weinre.web/modules/weinre/target/WiDOMStorageImpl.scoop
+++ b/weinre.web/modules/weinre/target/WiDOMStorageImpl.scoop
@@ -7,21 +7,164 @@
  */
 
 requireClass ../common/Weinre
+requireClass ../common/Native
 
 //-----------------------------------------------------------------------------
 class WiDOMStorageImpl
 
 //-----------------------------------------------------------------------------
 method getDOMStorageEntries(/*int*/ storageId, callback)
-    // callback: function(/*any[]*/ entries)
-    Weinre.notImplemented(arguments.callee.signature)
+    var storageArea = _getStorageArea(storageId)
+    
+    if (!storageArea) {
+        Weinre.logWarning(arguments.callee.signature + " passed an invalid storageId: " + storageId)
+        return
+    }
+    
+    var result = []
+    
+    var length = storageArea.length
+    for (var i=0; i<length; i++) {
+        var key = storageArea.key(i)
+        var val = storageArea.getItem(key)
+        
+        result.push([key, val])    
+    }
+    
+    if (callback) {
+        Weinre.WeinreTargetCommands.sendClientCallback(callback, [result])
+    }
 
 //-----------------------------------------------------------------------------
 method setDOMStorageItem(/*int*/ storageId, /*string*/ key, /*string*/ value, callback)
-    // callback: function(/*boolean*/ success)
-    Weinre.notImplemented(arguments.callee.signature)
+    var storageArea = _getStorageArea(storageId)
+    
+    if (!storageArea) {
+        Weinre.logWarning(arguments.callee.signature + " passed an invalid storageId: " + storageId)
+        return
+    }
+    
+    var result = true
+    try {
+        if (storageArea == window.localStorage) {
+            Native.LocalStorage_setItem(key, value)
+        }
+        else if (storageArea == window.sessionStorage) {
+            Native.SessionStorage_setItem(key, value)
+        }
+    }
+    catch (e) {
+        result = false
+    }
+
+    if (callback) {
+        Weinre.WeinreTargetCommands.sendClientCallback(callback, [result])
+    }
 
 //-----------------------------------------------------------------------------
 method removeDOMStorageItem(/*int*/ storageId, /*string*/ key, callback)
-    // callback: function(/*boolean*/ success)
-    Weinre.notImplemented(arguments.callee.signature)
\ No newline at end of file
+    var storageArea = _getStorageArea(storageId)
+    
+    if (!storageArea) {
+        Weinre.logWarning(arguments.callee.signature + " passed an invalid storageId: " + storageId)
+        return
+    }
+
+    var result = true
+    try {
+        if (storageArea == window.localStorage) {
+            Native.LocalStorage_removeItem(key)
+        }
+        else if (storageArea == window.sessionStorage) {
+            Native.SessionStorage_removeItem(key)
+        }
+    }
+    catch (e) {
+        result = false
+    }
+
+    if (callback) {
+        Weinre.WeinreTargetCommands.sendClientCallback(callback, [result])
+    }
+
+    
+//-----------------------------------------------------------------------------
+function _getStorageArea(storageId)
+    if (storageId == 1) {
+        return window.localStorage
+    }
+    
+    else if (storageId == 2) {
+        return window.sessionStorage
+    }
+    
+    return null
+
+//-----------------------------------------------------------------------------
+method initialize
+
+    if (window.localStorage) {
+        Weinre.wi.DOMStorageNotify.addDOMStorage({
+            id:             1,
+            host:           window.location.host,
+            isLocalStorage: true
+        })
+        
+        window.localStorage.setItem = function(key, value) {
+            Native.LocalStorage_setItem(key, value)
+            _storageEventHandler({storageArea: window.localStorage})
+        }
+        
+        window.localStorage.removeItem = function(key) {
+            Native.LocalStorage_removeItem(key)
+            _storageEventHandler({storageArea: window.localStorage})
+        }
+        
+        window.localStorage.clear = function() {
+            Native.LocalStorage_clear()
+            _storageEventHandler({storageArea: window.localStorage})
+        }
+    }
+    
+    if (window.sessionStorage) {
+        Weinre.wi.DOMStorageNotify.addDOMStorage({
+            id:             2,
+            host:           window.location.host,
+            isLocalStorage: false
+        })
+        
+        window.sessionStorage.setItem = function(key, value) {
+            Native.SessionStorage_setItem(key, value)
+            _storageEventHandler({storageArea: window.sessionStorage})
+        }
+        
+        window.sessionStorage.removeItem = function(key) {
+            Native.SessionStorage_removeItem(key)
+            _storageEventHandler({storageArea: window.sessionStorage})
+        }
+        
+        window.sessionStorage.clear = function() {
+            Native.SessionStorage_clear()
+            _storageEventHandler({storageArea: window.sessionStorage})
+        }
+    }
+    
+    document.addEventListener("storage", _storageEventHandler, false)
+    
+//-----------------------------------------------------------------------------
+function _storageEventHandler(event)
+    var storageId
+    
+    if (event.storageArea == window.localStorage) {
+        storageId = 1
+    }
+    
+    else if (event.storageArea == window.sessionStorage) {
+        storageId = 2
+    }
+    
+    else {
+        return
+    }
+    
+    Weinre.wi.DOMStorageNotify.updateDOMStorage(storageId)