sql support basically working
diff --git a/weinre.build/build.xml b/weinre.build/build.xml
index 9bee04d..1826ebd 100644
--- a/weinre.build/build.xml
+++ b/weinre.build/build.xml
@@ -290,10 +290,12 @@
         <delete dir="${CACHED}/json-idl"/>
         <mkdir  dir="${CACHED}/json-idl"/>
         
-        <simple-idl2json name="WeinreClientCommands"  oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
-        <simple-idl2json name="WeinreClientEvents"    oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
-        <simple-idl2json name="WeinreTargetCommands"  oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
-        <simple-idl2json name="WeinreTargetEvents"    oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
+        <simple-idl2json name="WeinreClientCommands"      oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
+        <simple-idl2json name="WeinreClientEvents"        oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
+        <simple-idl2json name="WeinreTargetCommands"      oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
+        <simple-idl2json name="WeinreTargetEvents"        oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
+        <simple-idl2json name="WeinreExtraClientCommands" oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
+        <simple-idl2json name="WeinreExtraTargetEvents"   oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
 
         <simple-idl2json name="InjectedScriptHost"    oDir="${CACHED}/json-idl" iDir="${VENDOR}/webkit/WebCore/inspector"/>
         
diff --git a/weinre.server/interfaces/WeinreClientCommands.idl b/weinre.server/interfaces/WeinreClientCommands.idl
index b912cdf..d0f86cb 100644
--- a/weinre.server/interfaces/WeinreClientCommands.idl
+++ b/weinre.server/interfaces/WeinreClientCommands.idl
@@ -14,7 +14,7 @@
 
         void getTargets(out Object[] targets);
         void getClients(out Object[] clients);
-        
+
         void connectTarget(in string clientId, in string targetId);
         void disconnectTarget(in string clientId);
         
diff --git a/weinre.server/interfaces/WeinreExtraClientCommands.idl b/weinre.server/interfaces/WeinreExtraClientCommands.idl
new file mode 100644
index 0000000..5d6fe5c
--- /dev/null
+++ b/weinre.server/interfaces/WeinreExtraClientCommands.idl
@@ -0,0 +1,17 @@
+/*
+ * weinre is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ * 
+ * Copyright (c) 2011 IBM Corporation
+ */
+
+// extra messages from the client to the target
+
+module weinre {
+    interface WeinreExtraClientCommands {
+    
+        void getDatabases(out Object[] databaseRecords);
+
+    };
+}
+
diff --git a/weinre.server/interfaces/WeinreExtraTargetEvents.idl b/weinre.server/interfaces/WeinreExtraTargetEvents.idl
new file mode 100644
index 0000000..58a6b72
--- /dev/null
+++ b/weinre.server/interfaces/WeinreExtraTargetEvents.idl
@@ -0,0 +1,17 @@
+/*
+ * weinre is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ * 
+ * Copyright (c) 2011 IBM Corporation
+ */
+
+// extra messages from the target to the client
+
+module weinre {
+    interface WeinreExtraTargetEvents {
+    
+        void databaseOpened(in Object databaseRecord);
+
+    };
+}
+
diff --git a/weinre.server/interfaces/WeinreTargetEvents.idl b/weinre.server/interfaces/WeinreTargetEvents.idl
index 36af730..5326b4b 100644
--- a/weinre.server/interfaces/WeinreTargetEvents.idl
+++ b/weinre.server/interfaces/WeinreTargetEvents.idl
@@ -14,7 +14,7 @@
         void connectionDestroyed(string clientId, string targetId);
         
         void sendCallback(string callbackId, Object result);
-
+        
     };
 }
 
diff --git a/weinre.web/demo/weinre-demo-pieces.html b/weinre.web/demo/weinre-demo-pieces.html
index adaac04..51b261f 100644
--- a/weinre.web/demo/weinre-demo-pieces.html
+++ b/weinre.web/demo/weinre-demo-pieces.html
@@ -43,6 +43,7 @@
 <script src="/weinre/target/InjectedScript.js"></script>
 <script src="/weinre/target/Timeline.transportd.js"></script>
 <script src="/weinre/target/SqlStepper.transportd.js"></script>
+<script src="/weinre/target/WeinreExtraClientCommandsImpl.transportd.js"></script>
 <script src="/interfaces/all-json-idls-min.js"></script>
 
 <script type="text/javascript">
diff --git a/weinre.web/demo/weinre-demo.js b/weinre.web/demo/weinre-demo.js
index a5dbecb..2a68fd2 100644
--- a/weinre.web/demo/weinre-demo.js
+++ b/weinre.web/demo/weinre-demo.js
@@ -44,7 +44,7 @@
         outputElement.innerHTML = ""
     })
     
-    setTimeout(_openDatabase,1000)
+    openTheDatabase()
 }
 
 //------------------------------------------------------------------------------
@@ -134,9 +134,9 @@
 }
 
 //------------------------------------------------------------------------------
-function _openDatabase() {
+function openTheDatabase() {
     if (window.openDatabase) {
-        db = window.openDatabase("clicks", "1.0", "clicks", 8192)
+        db = window.openDatabase("clicks_db", "1.0", "clicks", 8192)
         db.transaction(createDatabase)
     }
 }
diff --git a/weinre.web/modules/weinre/client/Client.scoop b/weinre.web/modules/weinre/client/Client.scoop
index f1368d8..73c499a 100644
--- a/weinre.web/modules/weinre/client/Client.scoop
+++ b/weinre.web/modules/weinre/client/Client.scoop
@@ -18,6 +18,7 @@
 requireClass ./InspectorBackendImpl
 requireClass ./InspectorFrontendHostImpl
 requireClass ./WeinreClientEventsImpl
+requireClass ./WeinreExtraTargetEventsImpl
 requireClass ./RemotePanel
 
 //-----------------------------------------------------------------------------
@@ -47,7 +48,10 @@
 
     // create the client commands proxy
     Weinre.WeinreClientCommands = messageDispatcher.createProxy("WeinreClientCommands")
+    Weinre.WeinreExtraClientCommands = messageDispatcher.createProxy("WeinreExtraClientCommands")
 
+    messageDispatcher.registerInterface("WeinreExtraTargetEvents", new WeinreExtraTargetEventsImpl(), false)
+    
     // register WebInspector interface
     messageDispatcher.registerInterface("WebInspector", WebInspector, false)
     
diff --git a/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop b/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop
index 459373d..7fd6a65 100644
--- a/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop
+++ b/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop
@@ -9,6 +9,8 @@
 requireClass ../common/Callback
 requireClass ../common/Weinre
 
+requireClass ./WeinreExtraTargetEventsImpl
+
 //-----------------------------------------------------------------------------
 class WeinreClientEventsImpl(client)
     this.client = client
@@ -67,6 +69,10 @@
     
     WebInspector.inspectedURLChanged(target.url)
 
+    Weinre.WeinreExtraClientCommands.getDatabases(function(databaseRecords) {
+        WeinreExtraTargetEventsImpl.addDatabaseRecords(databaseRecords)
+    })
+    
 //-----------------------------------------------------------------------------
 method connectionDestroyed(/*int*/ clientChannel, /*int*/ targetChannel)
 
diff --git a/weinre.web/modules/weinre/client/WeinreExtraTargetEventsImpl.scoop b/weinre.web/modules/weinre/client/WeinreExtraTargetEventsImpl.scoop
new file mode 100644
index 0000000..76abaad
--- /dev/null
+++ b/weinre.web/modules/weinre/client/WeinreExtraTargetEventsImpl.scoop
@@ -0,0 +1,48 @@
+
+/*
+ * weinre is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ * 
+ * Copyright (c) 2011 IBM Corporation
+ */
+
+//-----------------------------------------------------------------------------
+class WeinreExtraTargetEventsImpl
+
+//-----------------------------------------------------------------------------
+method databaseOpened(databaseRecord)
+    WeinreExtraTargetEventsImpl.addDatabaseRecords([databaseRecord])
+    
+//-----------------------------------------------------------------------------
+static method addDatabaseRecords(databaseRecords)
+    // databaseRecord.id
+    // databaseRecord.domain
+    // databaseRecord.name
+    // databaseRecord.version
+    
+    if (!WebInspector.panels) return
+    if (!WebInspector.panels.resources) return
+    if (!WebInspector.panels.resources._databases) return
+    
+    var existingDbs = WebInspector.panels.resources._databases
+    var existingDbNames = {}
+    
+    for (var i=0; i<existingDbs.length; i++) {
+        existingDbNames[existingDbs[i].name] = existingDbs[i]
+    }
+    
+    for (var i=0; i<databaseRecords.length; i++) {
+        if (existingDbNames[databaseRecords[i].name]) continue
+        
+        var databaseRecord = databaseRecords[i]
+        var database = new WebInspector.Database(
+            databaseRecord.id,
+            databaseRecord.domain,
+            databaseRecord.name,
+            databaseRecord.version
+            )
+        
+        WebInspector.panels.resources.addDatabase(database)
+    }
+    
+    
diff --git a/weinre.web/modules/weinre/target/Target.scoop b/weinre.web/modules/weinre/target/Target.scoop
index 0a4d81d..bb3eeae 100644
--- a/weinre.web/modules/weinre/target/Target.scoop
+++ b/weinre.web/modules/weinre/target/Target.scoop
@@ -21,6 +21,7 @@
 requireClass ./InjectedScriptHostImpl
 
 requireClass ./WeinreTargetEventsImpl
+requireClass ./WeinreExtraClientCommandsImpl
 
 requireClass ./WiConsoleImpl
 requireClass ./WiCSSImpl
@@ -45,15 +46,16 @@
     }
     
 //------------------------------------------------------------------------------
-method setWeinreServerURLFromScriptSrc()
+method setWeinreServerURLFromScriptSrc(element)
     if (window.WeinreServerURL) return
 
-    var element = this.getTargetScriptElement()
-    var pattern = /(http:\/\/(.*?)\/)/
-    var match   = pattern.exec(element.src)
-    if (match) {
-        window.WeinreServerURL = match[1]
-        return 
+    if (element) {
+        var pattern = /(http:\/\/(.*?)\/)/
+        var match   = pattern.exec(element.src)
+        if (match) {
+            window.WeinreServerURL = match[1]
+            return 
+        }
     }
     
     var message = "unable to calculate the weinre server url; explicity set the variable window.WeinreServerURL instead" 
@@ -62,14 +64,25 @@
 
 
 //-----------------------------------------------------------------------------
-method setWeinreServerIdFromScriptSrc()
+method setWeinreServerIdFromScriptSrc(element)
     if (window.WeinreServerId) return
 
     var element = this.getTargetScriptElement()
 
-    var hash = element.src.split("#")[1]
-    if (!hash) hash = "anonymous"
-    
+    var hash = "anonymous"
+    if (element) {
+        var attempt = element.src.split("#")[1]
+        if (attempt) {
+            hash = attempt
+        }
+        else {
+            attempt = location.hash.split("#")[1]
+            if (attempt) {
+                hash = attempt
+            }
+        }
+    }
+
     window.WeinreServerId = hash
 
 //-----------------------------------------------------------------------------
@@ -92,8 +105,9 @@
 method initialize()
     var self = this
 
-    this.setWeinreServerURLFromScriptSrc()
-    this.setWeinreServerIdFromScriptSrc()
+    var element = this.getTargetScriptElement()
+    this.setWeinreServerURLFromScriptSrc(element)
+    this.setWeinreServerIdFromScriptSrc(element)
     
     if (window.WeinreServerURL[window.WeinreServerURL.length-1] != "/") {
         window.WeinreServerURL += "/"
@@ -121,13 +135,13 @@
 
     Weinre.wi = {}
     
-    Weinre.wi.Console          = new WiConsoleImpl()
-    Weinre.wi.CSS              = new WiCSSImpl()
-    Weinre.wi.Database         = new WiDatabaseImpl()
-    Weinre.wi.DOM              = new WiDOMImpl()
-    Weinre.wi.DOMStorage       = new WiDOMStorageImpl()
-    Weinre.wi.Inspector        = new WiInspectorImpl()
-    Weinre.wi.Runtime          = new WiRuntimeImpl()
+    Weinre.wi.Console                   = new WiConsoleImpl()
+    Weinre.wi.CSS                       = new WiCSSImpl()
+    Weinre.wi.Database                  = new WiDatabaseImpl()
+    Weinre.wi.DOM                       = new WiDOMImpl()
+    Weinre.wi.DOMStorage                = new WiDOMStorageImpl()
+    Weinre.wi.Inspector                 = new WiInspectorImpl()
+    Weinre.wi.Runtime                   = new WiRuntimeImpl()
     
     messageDispatcher.registerInterface("Console",          Weinre.wi.Console          , false)
     messageDispatcher.registerInterface("CSS",              Weinre.wi.CSS              , false)
@@ -136,8 +150,9 @@
     messageDispatcher.registerInterface("DOMStorage",       Weinre.wi.DOMStorage       , false)
     messageDispatcher.registerInterface("Inspector",        Weinre.wi.Inspector        , false)
     messageDispatcher.registerInterface("Runtime",          Weinre.wi.Runtime          , false)
-    
-    messageDispatcher.registerInterface("WeinreTargetEvents", new WeinreTargetEventsImpl(), true)
+
+    messageDispatcher.registerInterface("WeinreExtraClientCommands",  new WeinreExtraClientCommandsImpl() , true)
+    messageDispatcher.registerInterface("WeinreTargetEvents",         new WeinreTargetEventsImpl(),         true)
 
     Weinre.wi.ApplicationCacheNotify = messageDispatcher.createProxy("ApplicationCacheNotify")
     Weinre.wi.ConsoleNotify          = messageDispatcher.createProxy("ConsoleNotify")
@@ -147,7 +162,8 @@
     Weinre.wi.InspectorNotify        = messageDispatcher.createProxy("InspectorNotify")
     Weinre.wi.TimelineNotify         = messageDispatcher.createProxy("TimelineNotify")
     
-    Weinre.WeinreTargetCommands  = messageDispatcher.createProxy("WeinreTargetCommands")
+    Weinre.WeinreTargetCommands     = messageDispatcher.createProxy("WeinreTargetCommands")
+    Weinre.WeinreExtraTargetEvents  = messageDispatcher.createProxy("WeinreExtraTargetEvents")
 
     messageDispatcher.getWebSocket().addEventListener("open", Binding(this, this.cb_webSocketOpened))
     
diff --git a/weinre.web/modules/weinre/target/WeinreExtraClientCommandsImpl.scoop b/weinre.web/modules/weinre/target/WeinreExtraClientCommandsImpl.scoop
new file mode 100644
index 0000000..28d6843
--- /dev/null
+++ b/weinre.web/modules/weinre/target/WeinreExtraClientCommandsImpl.scoop
@@ -0,0 +1,24 @@
+
+/*
+ * weinre is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ * 
+ * Copyright (c) 2010, 2011 IBM Corporation
+ */
+
+requireClass ../common/Weinre
+
+requireClass ./WiDatabaseImpl
+requireClass ./Console
+
+//-----------------------------------------------------------------------------
+class WeinreExtraClientCommandsImpl
+
+//-----------------------------------------------------------------------------
+method getDatabases(callback)
+    if (!callback) return
+    
+    var result = WiDatabaseImpl.getDatabases()
+    
+    Weinre.WeinreTargetCommands.sendClientCallback(callback, [result])
+
diff --git a/weinre.web/modules/weinre/target/WiDatabaseImpl.scoop b/weinre.web/modules/weinre/target/WiDatabaseImpl.scoop
index ed0c08b..e9fa6df 100644
--- a/weinre.web/modules/weinre/target/WiDatabaseImpl.scoop
+++ b/weinre.web/modules/weinre/target/WiDatabaseImpl.scoop
@@ -18,6 +18,16 @@
     window.openDatabase = wrappedOpenDatabase
 
 //-----------------------------------------------------------------------------
+static method getDatabases
+    var result = []
+    
+    for (var id in id2db) {
+        result.push(id2db[id])
+    }
+    
+    return result
+
+//-----------------------------------------------------------------------------
 function logSqlError(sqlError)
     console.log("SQL Error " + sqlError.code + ": " + sqlError.message)
 
@@ -52,12 +62,61 @@
     stepper.run(db, logSqlError)
 
 //-----------------------------------------------------------------------------
+function executeSQL_step_1()
+    this.executeSql(this.query);
+
+//-----------------------------------------------------------------------------
+function executeSQL_step_2(resultSet)
+    var columnNames = []
+    var values      = []
+    var rows        = resultSet.rows
+    
+    for (var i=0; i<rows.length; i++) {
+        var row = rows.item(i)
+        
+        if (i == 0) {
+            for (var propName in row) {
+                columnNames.push(propName)
+            }
+        }
+        
+        for (var j=0; j<columnNames.length; j++) {
+            values.push(row[columnNames[j]])
+        }
+    }
+
+    Weinre.wi.DatabaseNotify.sqlTransactionSucceeded(this.txid, columnNames, values)
+
+//-----------------------------------------------------------------------------
+function executeSQL_error(sqlError)
+    var error = {
+        code:    sqlError.code,
+        message: sqlError.message
+    }
+    
+    Weinre.wi.DatabaseNotify.sqlTransactionFailed(this.txid, error)
+
+//-----------------------------------------------------------------------------
 method executeSQL(/*int*/ databaseId, /*string*/ query, callback)
     var db = dbById(databaseId)
     if (!db) return
     
-    // callback: function(/*boolean*/ success, /*int*/ transactionId)
-    Weinre.notImplemented(arguments.callee.signature)
+    var txid = Weinre.targetDescription.channel + "-" + IDGenerator.next()
+    
+    var stepper = SqlStepper([
+        executeSQL_step_1,
+        executeSQL_step_2,
+    ])
+    
+    stepper.txid     = txid
+    stepper.query    = query
+    stepper.callback = callback
+    stepper.run(db, executeSQL_error)
+    
+    if (callback) {
+        Weinre.WeinreTargetCommands.sendClientCallback(callback, [true, txid])
+    }
+    
 
 //-----------------------------------------------------------------------------
 function wrappedOpenDatabase(name, version, displayName, estimatedSize, creationCallback)
@@ -94,29 +153,19 @@
     if (record) return record
     
     record = {}
-    record.db      = db
+    record.id      = IDGenerator.next()
+    record.domain  = window.location.origin
     record.name    = name
     record.version = version
-    record.id      = IDGenerator.next()
+    record.db      = db
     
     id2db[record.id] = record
     name2db[name]    = record
 
     var payload = {}
     payload.id      = record.id
-    payload.domain  = "???"
+    payload.domain  = record.domain
     payload.name    = name
     payload.version = version
     
-    Weinre.wi.DatabaseNotify.addDatabase(payload)
-
-//-----------------------------------------------------------------------------
-function dbGetAll()
-    var result = []
-    
-    for (var id in id2db) {
-        result.push(id2db[id])
-    }
-    
-    return result
-    
\ No newline at end of file
+    Weinre.WeinreExtraTargetEvents.databaseOpened(payload)