[CB-540] [weinre] easily navigate to spot in DOM

- Web Inspector has a few behaviors here that weinre didn't,
  and so these were added:

  - re-expanding to last selected DOM element on reload
  - expand to DOM element via the inspect() function

- most significant were WiDOMImpl:pushNodeByPathToFrontEnd
  and override in client of DOMNotify:setChildNodes to
  ignore calls made to previously set nodes

- a few drive-by clean ups were done

- added the common/Debug class which adds some nice logging
  methods for weinre developers
diff --git a/.wr b/.wr
index 7f87a8c..797e61e 100644
--- a/.wr
+++ b/.wr
@@ -28,7 +28,6 @@
 weinre.doc
 weinre.server/interfaces
 weinre.server/lib
-weinre.server/package.json
 weinre.server/README.md
 weinre.server/weinre
 weinre.server/weinre-hot
diff --git a/weinre.build/vendor.properties b/weinre.build/vendor.properties
index 1ba59f7..e773e5d 100644
--- a/weinre.build/vendor.properties
+++ b/weinre.build/vendor.properties
@@ -23,3 +23,5 @@
 
 WEBKIT_VERSION:          r78584
 WEBKIT_URL_PREFIX:       https://svn.webkit.org/repository/webkit/trunk
+
+# svn export -r r78584 https://svn.webkit.org/repository/webkit/trunk/Source/WebCore/inspector
diff --git a/weinre.web/modules/weinre/client/Client.coffee b/weinre.web/modules/weinre/client/Client.coffee
index 41acfd9..54422a4 100644
--- a/weinre.web/modules/weinre/client/Client.coffee
+++ b/weinre.web/modules/weinre/client/Client.coffee
@@ -42,6 +42,9 @@
 
     #---------------------------------------------------------------------------
     initialize: ->
+    
+        addHack_DOMNotify_setChildNodes()
+        
         window.addEventListener 'load', Binding(this, 'onLoaded'), false
 
         messageDispatcher = new MessageDispatcher('../ws/client', @_getId())
@@ -126,8 +129,28 @@
         Weinre.client.initialize()
 
         window.installWebInspectorAPIsource = installWebInspectorAPIsource
+    
 
 #-------------------------------------------------------------------------------
+old_DOMNotify_setChildNodes = null
+
+#-------------------------------------------------------------------------------
+new_DOMNotify_setChildNodes = (parentId, payloads) ->
+    domNode  = this._domAgent._idToDOMNode[parentId]
+
+    if domNode.children 
+        if domNode.children.length > 0
+            return
+    
+    old_DOMNotify_setChildNodes.call(this, parentId, payloads)
+
+#-------------------------------------------------------------------------------
+addHack_DOMNotify_setChildNodes = ->
+    old_DOMNotify_setChildNodes = WebInspector.DOMDispatcher::setChildNodes
+    
+    WebInspector.DOMDispatcher::setChildNodes = new_DOMNotify_setChildNodes
+    
+#-------------------------------------------------------------------------------
 installWebInspectorAPIsource = () ->
       return if 'webInspector' of window
 
diff --git a/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.coffee b/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.coffee
index d4e258b..35728e3 100644
--- a/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.coffee
+++ b/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.coffee
@@ -30,6 +30,9 @@
         @_getPlatformAndPort()
 
     #---------------------------------------------------------------------------
+    showContextMenu: ->
+
+    #---------------------------------------------------------------------------
     loaded: ->
 
     #---------------------------------------------------------------------------
diff --git a/weinre.web/modules/weinre/common/Debug.coffee b/weinre.web/modules/weinre/common/Debug.coffee
new file mode 100644
index 0000000..545de8a
--- /dev/null
+++ b/weinre.web/modules/weinre/common/Debug.coffee
@@ -0,0 +1,69 @@
+
+#-------------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#-------------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------------
+module.exports = new class Debug
+
+    #---------------------------------------------------------------------------
+    constructor: ->
+        @_printCalledArgs = {}
+
+    #---------------------------------------------------------------------------
+    log: (message) -> 
+        console = window.console.__original || window.console
+        console.log "#{@timeStamp()}: #{message}"
+
+    #---------------------------------------------------------------------------
+    logCall: (context, intf, method, args, message) ->
+        if message
+            message = ": #{message}"
+        else
+            message = ""
+        
+        signature = @signature(intf, method)
+        printArgs = @_printCalledArgs[signature]
+        
+        if printArgs
+            args = JSON.stringify(args,null,4)
+        else
+            args = ""
+        
+        @log "#{context} #{signature}(#{args})#{message}"
+
+    #---------------------------------------------------------------------------
+    logCallArgs: (intf, method) -> 
+        @_printCalledArgs[@signature(intf, method)] = true
+
+    #---------------------------------------------------------------------------
+    signature: (intf, method) ->
+        "#{intf}.#{method}"
+    
+    #---------------------------------------------------------------------------
+    timeStamp: ->
+        date = new Date()
+        
+        mins = "#{date.getMinutes()}"
+        secs = "#{date.getSeconds()}"
+        
+        mins = "0#{mins}" if mins.length == 1
+        secs = "0#{secs}" if secs.length == 1
+        
+        "#{mins}:#{secs}"
+    
\ No newline at end of file
diff --git a/weinre.web/modules/weinre/common/MessageDispatcher.coffee b/weinre.web/modules/weinre/common/MessageDispatcher.coffee
index 37a0cc4..554f0c6 100644
--- a/weinre.web/modules/weinre/common/MessageDispatcher.coffee
+++ b/weinre.web/modules/weinre/common/MessageDispatcher.coffee
@@ -24,11 +24,19 @@
 Binding      = require('./Binding')
 Ex           = require('./Ex')
 Callback     = require('./Callback')
+#Debug        = require('./Debug')
 
 Verbose = false
 InspectorBackend = null
 
 #-------------------------------------------------------------------------------
+#Debug.logCallArgs "DOM", "addInspectedNode"
+#Debug.logCallArgs "DOM", "pushNodeByPathToFrontend"
+#Debug.logCallArgs "DOM",  "getChildNodes"
+#Debug.logCallArgs "DOMNotify", "setChildNodes"
+#Debug.logCallArgs "DOMNotify", "setDocument"
+
+#-------------------------------------------------------------------------------
 module.exports = class MessageDispatcher
 
     #---------------------------------------------------------------------------
@@ -112,6 +120,7 @@
             method:    methodName
             args:      args
 
+        #Debug.logCall "send", intfName, methodName, args
         data = JSON.stringify(data)
         @_socket.send data
 
@@ -163,7 +172,7 @@
         intfName = data["interface"]
         methodName = data.method
         args = data.args
-        methodSignature = intfName + ".#{methodName}()"
+        methodSignature = "#{intfName}.#{methodName}()"
         intf = @_interfaces.hasOwnProperty(intfName) and @_interfaces[intfName]
 
         if not intf and InspectorBackend and intfName.match(/.*Notify/)
@@ -179,6 +188,8 @@
         unless typeof method == "function"
             Weinre.notImplemented methodSignature
             return
+            
+        #Debug.logCall "hand", intfName, methodName, args
         try
             method.apply intf, args
         catch e
diff --git a/weinre.web/modules/weinre/target/InjectedScriptHostImpl.coffee b/weinre.web/modules/weinre/target/InjectedScriptHostImpl.coffee
index 0358fd9..3469819 100644
--- a/weinre.web/modules/weinre/target/InjectedScriptHostImpl.coffee
+++ b/weinre.web/modules/weinre/target/InjectedScriptHostImpl.coffee
@@ -39,6 +39,9 @@
         children = Weinre.nodeStore.serializeNode(node, 1)
         Weinre.wi.DOMNotify.setChildNodes nodeId, children
         Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+        
+        if selectInUI
+            Weinre.wi.InspectorNotify.updateFocusedNode nodeId
 
     #---------------------------------------------------------------------------
     inspectedNode: (num, callback) ->
diff --git a/weinre.web/modules/weinre/target/NodeStore.coffee b/weinre.web/modules/weinre/target/NodeStore.coffee
index c80339c..a78f2ae 100644
--- a/weinre.web/modules/weinre/target/NodeStore.coffee
+++ b/weinre.web/modules/weinre/target/NodeStore.coffee
@@ -21,13 +21,15 @@
 Weinre      = require('../common/Weinre')
 IDGenerator = require('../common/IDGenerator')
 
+Debug       = require('../common/Debug')
+
 #-------------------------------------------------------------------------------
 module.exports = class NodeStore
 
     constructor: ->
-        @__nodeMap      = {}
-        @__nodeDataMap  = {}
-        @inspectedNodes = []
+        @_nodeMap      = {}
+        @_childrenSent = {}
+        @_inspectedNodes = []
 
         document.addEventListener "DOMSubtreeModified",       handleDOMSubtreeModified, false
         document.addEventListener "DOMNodeInserted",          handleDOMNodeInserted, false
@@ -37,16 +39,16 @@
 
     #---------------------------------------------------------------------------
     addInspectedNode: (nodeId) ->
-        @inspectedNodes.unshift nodeId
-        @inspectedNodes = @inspectedNodes.slice(0, 5) if @inspectedNodes.length > 5
+        @_inspectedNodes.unshift nodeId
+        @_inspectedNodes = @_inspectedNodes.slice(0, 5) if @_inspectedNodes.length > 5
 
     #---------------------------------------------------------------------------
     getInspectedNode: (index) ->
-        @inspectedNodes[index]
+        @_inspectedNodes[index]
 
     #---------------------------------------------------------------------------
     getNode: (nodeId) ->
-        @__nodeMap[nodeId]
+        @_nodeMap[nodeId]
 
     #---------------------------------------------------------------------------
     checkNodeId: (node) ->
@@ -56,7 +58,7 @@
     getNodeId: (node) ->
         id = @checkNodeId(node)
         return id if id
-        IDGenerator.getId node, @__nodeMap
+        IDGenerator.getId node, @_nodeMap
 
     #---------------------------------------------------------------------------
     getNodeData: (nodeId, depth) ->
diff --git a/weinre.web/modules/weinre/target/WiDOMImpl.coffee b/weinre.web/modules/weinre/target/WiDOMImpl.coffee
index 7d83ac8..7cc8da3 100644
--- a/weinre.web/modules/weinre/target/WiDOMImpl.coffee
+++ b/weinre.web/modules/weinre/target/WiDOMImpl.coffee
@@ -135,7 +135,31 @@
 
     #---------------------------------------------------------------------------
     pushNodeByPathToFrontend: (path, callback) ->
-        Weinre.notImplemented arguments.callee.signature
+        parts = path.split(",")
+        
+        curr   = document
+        currId = null
+        
+        nodeId = Weinre.nodeStore.getNodeId(curr)
+        @getChildNodes(nodeId)
+        
+        for i in [0...parts.length] by 2
+            index    = parseInt(parts[i])
+            nodeName = parts[i+1]
+            
+            return if isNaN(index) 
+            
+            childNodeIds = Weinre.nodeStore.childNodeIds(curr)
+            currId = childNodeIds[index]
+            return if !currId
+            
+            @getChildNodes(currId)
+            curr = Weinre.nodeStore.getNode(currId)
+            
+            return if curr.nodeName != nodeName
+
+        if callback && currId
+            Weinre.WeinreTargetCommands.sendClientCallback callback, [ currId ]
 
     #---------------------------------------------------------------------------
     resolveNode: (nodeId, callback) ->