making a little more headway
diff --git a/weinre.web/demo/weinre-demo-pieces.html b/weinre.web/demo/weinre-demo-pieces.html
index f450475..adaac04 100644
--- a/weinre.web/demo/weinre-demo-pieces.html
+++ b/weinre.web/demo/weinre-demo-pieces.html
@@ -9,8 +9,7 @@
 <head>
 <meta name="viewport" content="user-scalable=no, width=device-width, height=device-height">
 <title>weinre demo</title>
-<link rel="stylesheet" href="weinre-demo.css">
-<script src="weinre-demo.js"></script>
+
 <script src="/modjewel-require.js"></script>
 <script type="text/javascript">require("modjewel").warnOnRecursiveRequire(true)</script>
 <script src="/scooj.transportd.js"></script>
@@ -43,12 +42,16 @@
 <script src="/weinre/target/ElementHighlighter.transportd.js"></script>
 <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="/interfaces/all-json-idls-min.js"></script>
 
 <script type="text/javascript">
     require("weinre/common/Weinre").getClass().showNotImplemented()
     require('weinre/target/Target').getClass().main()
 </script>
+
+<link rel="stylesheet" href="weinre-demo.css">
+<script src="weinre-demo.js"></script>
 </head>
 
 <body onload="onLoad()">
diff --git a/weinre.web/demo/weinre-demo.js b/weinre.web/demo/weinre-demo.js
index 5789828..a5dbecb 100644
--- a/weinre.web/demo/weinre-demo.js
+++ b/weinre.web/demo/weinre-demo.js
@@ -12,6 +12,7 @@
 var buttonClearOutput
 var outputElement 
 var storageIndex = 0
+var db
 
 // set the id based on the hash
 var hash = location.href.split("#")[1]
@@ -26,7 +27,7 @@
     
     buttonStartStuff.addEventListener("click", function() {
         lastClickTime = new Date().toString()
-        db.transaction(addClick)
+        if (db) db.transaction(addClick)
         
         if (!started) {
             buttonStartStuff.value = "stop stuff"
@@ -43,6 +44,7 @@
         outputElement.innerHTML = ""
     })
     
+    setTimeout(_openDatabase,1000)
 }
 
 //------------------------------------------------------------------------------
@@ -132,10 +134,11 @@
 }
 
 //------------------------------------------------------------------------------
-var db
-if (window.openDatabase) {
-    db = window.openDatabase("clicks", "1.0", "clicks", 8192)
-    db.transaction(createDatabase)
+function _openDatabase() {
+    if (window.openDatabase) {
+        db = window.openDatabase("clicks", "1.0", "clicks", 8192)
+        db.transaction(createDatabase)
+    }
 }
 
 //------------------------------------------------------------------------------
diff --git a/weinre.web/modules/weinre/target/SqlStepper.scoop b/weinre.web/modules/weinre/target/SqlStepper.scoop
new file mode 100644
index 0000000..3789812
--- /dev/null
+++ b/weinre.web/modules/weinre/target/SqlStepper.scoop
@@ -0,0 +1,92 @@
+
+/*
+ * 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/Binding
+
+//-----------------------------------------------------------------------------
+class SqlStepper(steps)
+    if (!(this instanceof SqlStepper)) return new SqlStepper(steps)
+    
+    this.__context = {}
+    
+    var context = this.__context
+    context.steps = steps
+    
+//-----------------------------------------------------------------------------
+method run(db, errorCallback)
+    var context = this.__context
+    
+    if (context.hasBeenRun) 
+        throw new Ex(arguments, "stepper has already been run")
+        
+    context.hasBeenRun = true
+        
+    context.db            = db
+    context.errorCallback = errorCallback
+    context.nextStep      = 0
+    
+    context.ourErrorCallback = new Binding(this, ourErrorCallback)
+    context.runStep          = new Binding(this, runStep)
+    this.executeSql          = new Binding(this, executeSql)
+    
+    db.transaction(context.runStep)
+    
+//-----------------------------------------------------------------------------
+function executeSql(statement, data)
+    var context = this.__context
+    
+    context.tx.executeSql(statement, data, context.runStep, context.ourErrorCallback)
+
+//-----------------------------------------------------------------------------
+function ourErrorCallback(tx, sqlError)
+    var context = this.__context
+    
+    context.errorCallback.call(this, sqlError)
+    
+//-----------------------------------------------------------------------------
+function runStep(tx, resultSet)
+    var context = this.__context
+    
+    if (context.nextStep >= context.steps.length) return
+    
+    context.tx = tx
+    
+    context.currentStep = context.nextStep
+    context.nextStep++
+    
+    var step = context.steps[context.currentStep]
+    
+    step.call(this, resultSet)
+
+//-----------------------------------------------------------------------------
+static method example(db, id)
+    function step1() {
+        this.executeSql("SELECT name FROM sqlite_master WHERE type='table'")
+    }
+    
+    function step2(resultSet) {
+        var rows = resultSet.rows
+        var result = []
+        for (var i=0; i<rows.length; i++) {
+            var name = rows.item(i).name
+            if (name == "__WebKitDatabaseInfoTable__") continue
+        
+            result.push(name)
+        }
+        
+        console.log("[" + this.id + "] table names: " + result.join(", "))
+    }
+
+    function errorCb(sqlError) {
+        
+        console.log("[" + this.id + "] sql error:" + sqlError.code + ": " + sqlError.message)
+    }
+    
+    var stepper = new SqlStepper([step1, step2])
+    stepper.id = id
+    stepper.run(db, errorCb)
diff --git a/weinre.web/modules/weinre/target/WiDatabaseImpl.scoop b/weinre.web/modules/weinre/target/WiDatabaseImpl.scoop
index be7c66f..ed0c08b 100644
--- a/weinre.web/modules/weinre/target/WiDatabaseImpl.scoop
+++ b/weinre.web/modules/weinre/target/WiDatabaseImpl.scoop
@@ -8,29 +8,115 @@
 
 requireClass ../common/Weinre
 requireClass ../common/Native
+requireClass ../common/IDGenerator
+requireClass ./SqlStepper
 
 //-----------------------------------------------------------------------------
 class WiDatabaseImpl
     if (!window.openDatabase) return
     
-    window.openDatabase = nativeOpenDatabase
+    window.openDatabase = wrappedOpenDatabase
 
 //-----------------------------------------------------------------------------
-method getDatabaseTableNames(/*int*/ databaseId, callback)
-    // callback: function(/*any[]*/ tableNames)
-    Weinre.notImplemented(arguments.callee.signature)
+function logSqlError(sqlError)
+    console.log("SQL Error " + sqlError.code + ": " + sqlError.message)
 
+//-----------------------------------------------------------------------------
+function getTableNames_step_1() 
+    this.executeSql("SELECT name FROM sqlite_master WHERE type='table'");
+
+//-----------------------------------------------------------------------------
+function getTableNames_step_2(resultSet) 
+    var rows = resultSet.rows
+    var result = []
+    for (var i=0; i<rows.length; i++) {
+        var name = rows.item(i).name
+        if (name == "__WebKitDatabaseInfoTable__") continue
+        
+        result.push(name)
+    }
+    
+    Weinre.WeinreTargetCommands.sendClientCallback(this.callback, [result])
+
+//-----------------------------------------------------------------------------
+method getDatabaseTableNames( databaseId, callback)
+    var db = dbById(databaseId)
+    if (!db) return
+  
+    var stepper = SqlStepper([
+        getTableNames_step_1, 
+        getTableNames_step_2
+    ])
+    
+    stepper.callback = callback
+    stepper.run(db, logSqlError)
 
 //-----------------------------------------------------------------------------
 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)
 
 //-----------------------------------------------------------------------------
-function nativeOpenDatabase(name, version, displayName, estimatedSize, creationCallback)
+function wrappedOpenDatabase(name, version, displayName, estimatedSize, creationCallback)
+
+    var db = Native.openDatabase(name, version, displayName, estimatedSize, creationCallback)
     
-    Weinre.wi.DatabaseNotify.addDatabase(name)
+    dbAdd(db, name, version)
     
-    return Native.openDatabase(name, version, displayName, estimatedSize, creationCallback)
+    return db    
     
+//-----------------------------------------------------------------------------
+init 
+    var id2db   = {}
+    var name2db = {}
+
+//-----------------------------------------------------------------------------
+function dbById(id) 
+    var record = id2db[id]
+    if (!record) return null
+    return record.db
+    
+//-----------------------------------------------------------------------------
+function dbRecordById(id) 
+    return id2db[id]
+    
+//-----------------------------------------------------------------------------
+function dbRecordByName(name) 
+    return name2db[name]
+    
+//-----------------------------------------------------------------------------
+function dbAdd(db, name, version)
+    
+    var record = dbRecordByName(name)
+    if (record) return record
+    
+    record = {}
+    record.db      = db
+    record.name    = name
+    record.version = version
+    record.id      = IDGenerator.next()
+    
+    id2db[record.id] = record
+    name2db[name]    = record
+
+    var payload = {}
+    payload.id      = record.id
+    payload.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