Patch refactors SessionHandler and BrowserChannelClient to enable OOPHM clients
other than HtmlUnit. Removes need for UnsupportedOperationException and adds
generics to SessionHandler.

Patch by: t.broyer@gmail.com
Review by: amitmanjhi, jat


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7603 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java b/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java
index 98569c6..be5c3b3 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java
@@ -15,7 +15,6 @@
  */
 package com.google.gwt.dev.shell;
 
-import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.ExceptionOrReturnValue;
 import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.SpecialDispatchId;
 import com.google.gwt.dev.shell.BrowserChannel.Value.ValueType;
@@ -198,7 +197,7 @@
   /**
    * Hook interface for responding to messages.
    */
-  public abstract static class SessionHandler {
+  public abstract static class SessionHandler<T extends BrowserChannel> {
 
     /**
      * Wrapper to return both a return value/exception and a flag as to whether
@@ -244,37 +243,7 @@
       }
     }
 
-    public abstract void freeValue(BrowserChannel channel, int[] ids);
-
-    public abstract ExceptionOrReturnValue getProperty(BrowserChannel channel,
-        int refId, int dispId);
-
-    public abstract ExceptionOrReturnValue invoke(BrowserChannel channel,
-        Value thisObj, int dispId, Value[] args);
-
-    /**
-     * Load a new instance of a module.
-     *
-     * @param channel
-     * @param moduleName
-     * @param userAgent
-     * @param url top-level URL of the main page, null if using an old plugin
-     * @param tabKey opaque key of the tab, may be empty if the plugin can't
-     *     distinguish tabs or null if using an old plugin
-     * @param sessionKey opaque key for this session, null if using an old plugin
-     * @param userAgentIcon byte array containing an icon (which fits within
-     *     24x24) representing the user agent or null if unavailable
-     * @return a TreeLogger to use for the module's logs, or null if the module
-     *     load failed
-     */
-    public abstract TreeLogger loadModule(BrowserChannel channel,
-        String moduleName, String userAgent, String url, String tabKey,
-        String sessionKey, byte[] userAgentIcon);
-
-    public abstract ExceptionOrReturnValue setProperty(BrowserChannel channel,
-        int refId, int dispId, Value newValue);
-
-    public abstract void unloadModule(BrowserChannel channel, String moduleName);
+    public abstract void freeValue(T channel, int[] ids);
   }
 
   /**
@@ -1639,101 +1608,6 @@
         + socket.getPort();
   }
 
-  public Value invoke(String methodName, Value vthis, Value[] vargs,
-      SessionHandler handler) throws IOException, BrowserChannelException {
-    new InvokeOnClientMessage(this, methodName, vthis, vargs).send();
-    final ReturnMessage msg = reactToMessagesWhileWaitingForReturn(handler);
-    return msg.returnValue;
-  }
-
-  /**
-   * React to messages from the other side, where no return value is expected.
-   * 
-   * @param handler
-   * @throws RemoteDeathError
-   */
-  public void reactToMessages(SessionHandler handler) {
-    do {
-      try {
-        getStreamToOtherSide().flush();
-        MessageType messageType = Message.readMessageType(
-            getStreamFromOtherSide());
-        switch (messageType) {
-          case FREE_VALUE:
-            final FreeMessage freeMsg = FreeMessage.receive(this);
-            handler.freeValue(this, freeMsg.getIds());
-            break;
-          case INVOKE:
-            InvokeOnServerMessage imsg = InvokeOnServerMessage.receive(this);
-            ExceptionOrReturnValue result = handler.invoke(this, imsg.getThis(),
-                imsg.getMethodDispatchId(), imsg.getArgs());
-            sendFreedValues();
-            ReturnMessage.send(this, result);
-            break;
-          case INVOKE_SPECIAL:
-            handleInvokeSpecial(handler);
-            break;
-          case QUIT:
-            return;
-          default:
-            throw new RemoteDeathError(new BrowserChannelException(
-                "Invalid message type " + messageType));
-        }
-      } catch (IOException e) {
-        throw new RemoteDeathError(e);
-      } catch (BrowserChannelException e) {
-        throw new RemoteDeathError(e);
-      }
-    } while (true);
-  }
-
-  /**
-   * React to messages from the other side, where a return value is expected.
-   * 
-   * @param handler
-   * @throws BrowserChannelException 
-   * @throws RemoteDeathError
-   */
-  public ReturnMessage reactToMessagesWhileWaitingForReturn(
-      SessionHandler handler) throws BrowserChannelException, RemoteDeathError {
-    do {
-      try {
-        getStreamToOtherSide().flush();
-        MessageType messageType = Message.readMessageType(
-            getStreamFromOtherSide());
-        switch (messageType) {
-          case FREE_VALUE:
-            final FreeMessage freeMsg = FreeMessage.receive(this);
-            handler.freeValue(this, freeMsg.getIds());
-            break;
-          case RETURN:
-            return ReturnMessage.receive(this);
-          case INVOKE:
-            InvokeOnServerMessage imsg = InvokeOnServerMessage.receive(this);
-            ExceptionOrReturnValue result = handler.invoke(this, imsg.getThis(),
-                imsg.getMethodDispatchId(), imsg.getArgs());
-            sendFreedValues();
-            ReturnMessage.send(this, result);
-            break;
-          case INVOKE_SPECIAL:
-            handleInvokeSpecial(handler);
-            break;
-          case QUIT:
-            // if we got an unexpected QUIT here, the remote plugin probably
-            // realized it was dying and had time to close the socket properly.
-            throw new RemoteDeathError(null);
-          default:
-            throw new BrowserChannelException("Invalid message type "
-                + messageType + " received waiting for return.");
-        }
-      } catch (IOException e) {
-        throw new RemoteDeathError(e);
-      } catch (BrowserChannelException e) {
-        throw new RemoteDeathError(e);
-      }
-    } while (true);
-  }
-
   protected DataInputStream getStreamFromOtherSide() {
     return streamFromOtherSide;
   }
@@ -1797,6 +1671,19 @@
     return value;
   }
 
+  protected void sendFreedValues() throws IOException {
+    Set<Integer> freed = objectRefFactory.getRefIdsForCleanup();
+    int n = freed.size();
+    if (n > 0) {
+      int[] ids = new int[n];
+      int i = 0;
+      for (Integer id : freed) {
+        ids[i++] = id;
+      }
+      FreeMessage.send(this, ids);
+    }
+  }
+
   protected void writeValue(DataOutputStream stream, Value value)
       throws IOException {
     if (value.isNull()) {
@@ -1827,39 +1714,4 @@
       assert false;
     }
   }
-
-  private void handleInvokeSpecial(SessionHandler handler) throws IOException,
-      BrowserChannelException {
-    final InvokeSpecialMessage ismsg = InvokeSpecialMessage.receive(this);
-    Value[] args = ismsg.getArgs();
-    ExceptionOrReturnValue retExc = null;
-    switch (ismsg.getDispatchId()) {
-      case GetProperty:
-        assert args.length == 2;
-        retExc = handler.getProperty(this, args[0].getInt(), args[1].getInt());
-        break;
-      case SetProperty:
-        assert args.length == 3;
-        retExc = handler.setProperty(this, args[0].getInt(), args[1].getInt(),
-            args[2]);
-        break;
-      default:
-        throw new HostedModeException("Unexpected InvokeSpecial method "
-            + ismsg.getDispatchId());
-    }
-    ReturnMessage.send(this, retExc);
-  }
-
-  private void sendFreedValues() throws IOException {
-    Set<Integer> freed = objectRefFactory.getRefIdsForCleanup();
-    int n = freed.size();
-    if (n > 0) {
-      int[] ids = new int[n];
-      int i = 0;
-      for (Integer id : freed) {
-        ids[i++] = id;
-      }
-      FreeMessage.send(this, ids);
-    }
-  }
 }
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserChannelClient.java b/dev/core/src/com/google/gwt/dev/shell/BrowserChannelClient.java
index 6a7f56a..bae89b7 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserChannelClient.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserChannelClient.java
@@ -25,10 +25,26 @@
 
 /**
  * Implementation of the BrowserChannel for the client side.
- * 
  */
 public class BrowserChannelClient extends BrowserChannel {
 
+  /**
+   * Hook interface for responding to messages from the server.
+   */
+  public abstract static class SessionHandlerClient extends
+      SessionHandler<BrowserChannelClient> {
+
+    public abstract Object getSynchronizationObject();
+
+    public abstract String getUserAgent();
+
+    public abstract ExceptionOrReturnValue invoke(BrowserChannelClient channel,
+        Value thisObj, String methodName, Value[] args);
+
+    public abstract void loadJsni(BrowserChannelClient channel,
+        String jsniString);
+  }
+
   private static class ClientObjectRefFactory implements ObjectRefFactory {
 
     private final RemoteObjectTable<JavaObjectRef> remoteObjectTable;
@@ -55,7 +71,7 @@
     }
   }
 
-  private final HtmlUnitSessionHandler htmlUnitSessionHandler;
+  private final SessionHandlerClient handler;
   private final PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
   private final String moduleName;
   private final String tabKey;
@@ -67,7 +83,7 @@
 
   public BrowserChannelClient(String addressParts[], String url,
       String sessionKey, String moduleName, String versionString,
-      HtmlUnitSessionHandler htmlUnitSessionHandler) throws IOException {
+      SessionHandlerClient sessionHandlerClient) throws IOException {
     super(new Socket(addressParts[0], Integer.parseInt(addressParts[1])),
         new ClientObjectRefFactory());
     connected = true;
@@ -79,7 +95,7 @@
     logger.setMaxDetail(TreeLogger.WARN);
     logger.log(TreeLogger.SPAM, "BrowserChannelClient, versionString: "
         + versionString);
-    this.htmlUnitSessionHandler = htmlUnitSessionHandler;
+    this.handler = sessionHandlerClient;
   }
 
   public boolean disconnectFromHost() throws IOException {
@@ -97,7 +113,7 @@
 
   /**
    * @return the negotiated protocol version -- only valid after {@link #init}
-   * has returned.
+   *         has returned.
    */
   public int getProtocolVersion() {
     return protocolVersion;
@@ -117,12 +133,12 @@
       return false;
     }
     logger.log(TreeLogger.DEBUG, "sending " + MessageType.LOAD_MODULE
-        + " message, userAgent: " + htmlUnitSessionHandler.getUserAgent());
+        + " message, userAgent: " + handler.getUserAgent());
     ReturnMessage returnMessage = null;
-    synchronized (htmlUnitSessionHandler.getHtmlPage()) {
+    synchronized (handler.getSynchronizationObject()) {
       new LoadModuleMessage(this, url, tabKey, sessionKey, moduleName,
-          htmlUnitSessionHandler.getUserAgent()).send();
-      returnMessage = reactToMessages(htmlUnitSessionHandler, true);
+          handler.getUserAgent()).send();
+      returnMessage = reactToMessages(handler, true);
     }
     logger.log(TreeLogger.DEBUG, "loaded module, returnValue: "
         + returnMessage.getReturnValue() + ", isException: "
@@ -131,8 +147,7 @@
   }
 
   public ReturnMessage reactToMessagesWhileWaitingForReturn(
-      HtmlUnitSessionHandler handler) throws IOException,
-      BrowserChannelException {
+      SessionHandlerClient handler) throws IOException, BrowserChannelException {
     ReturnMessage returnMessage = reactToMessages(handler, true);
     return returnMessage;
   }
@@ -167,9 +182,8 @@
     return true;
   }
 
-  private ReturnMessage reactToMessages(
-      HtmlUnitSessionHandler htmlUnitSessionHandler, boolean expectReturn)
-      throws IOException, BrowserChannelException {
+  private ReturnMessage reactToMessages(SessionHandlerClient handler,
+      boolean expectReturn) throws IOException, BrowserChannelException {
     while (true) {
       ExceptionOrReturnValue returnValue;
       MessageType type = Message.readMessageType(getStreamFromOtherSide());
@@ -179,21 +193,8 @@
         switch (type) {
           case INVOKE:
             InvokeOnClientMessage invokeMessage = InvokeOnClientMessage.receive(this);
-            returnValue = htmlUnitSessionHandler.invoke(this,
-                invokeMessage.getThis(), invokeMessage.getMethodName(),
-                invokeMessage.getArgs());
-            htmlUnitSessionHandler.sendFreeValues(this);
-            new ReturnMessage(this, returnValue.isException(),
-                returnValue.getReturnValue()).send();           
-            break;
-          case INVOKE_SPECIAL:
-            InvokeSpecialMessage invokeSpecialMessage = InvokeSpecialMessage.receive(this);
-            logger.log(TreeLogger.DEBUG, type + " message " + ", thisRef: "
-                + invokeSpecialMessage.getArgs());
-            returnValue = htmlUnitSessionHandler.invokeSpecial(this,
-                invokeSpecialMessage.getDispatchId(),
-                invokeSpecialMessage.getArgs());
-            htmlUnitSessionHandler.sendFreeValues(this);
+            returnValue = handler.invoke(this, invokeMessage.getThis(),
+                invokeMessage.getMethodName(), invokeMessage.getArgs());
             new ReturnMessage(this, returnValue.isException(),
                 returnValue.getReturnValue()).send();
             break;
@@ -201,18 +202,18 @@
             FreeMessage freeMessage = FreeMessage.receive(this);
             logger.log(TreeLogger.DEBUG, type + " message "
                 + freeMessage.getIds());
-            htmlUnitSessionHandler.freeValue(this, freeMessage.getIds());
+            handler.freeValue(this, freeMessage.getIds());
             // no response
             break;
           case LOAD_JSNI:
             LoadJsniMessage loadJsniMessage = LoadJsniMessage.receive(this);
             String jsniString = loadJsniMessage.getJsni();
-            htmlUnitSessionHandler.loadJsni(this, jsniString);
+            handler.loadJsni(this, jsniString);
             // no response
             break;
           case REQUEST_ICON:
             RequestIconMessage.receive(this);
-            // no need for icon here 
+            // no need for icon here
             UserAgentIconMessage.send(this, null);
             break;
           case RETURN:
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java b/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
index 682ce65..f81101b 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
@@ -17,6 +17,7 @@
 
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.TreeLogger.HelpInfo;
+import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.ExceptionOrReturnValue;
 import com.google.gwt.dev.shell.JsValue.DispatchObject;
 
 import java.io.IOException;
@@ -34,6 +35,41 @@
  */
 public class BrowserChannelServer extends BrowserChannel
     implements Runnable {
+  
+  /**
+   * Hook interface for responding to messages from the client.
+   */
+  public abstract static class SessionHandlerServer extends SessionHandler<BrowserChannelServer> {
+    public abstract ExceptionOrReturnValue getProperty(BrowserChannelServer channel,
+        int refId, int dispId);
+
+    public abstract ExceptionOrReturnValue invoke(BrowserChannelServer channel,
+        Value thisObj, int dispId, Value[] args);
+
+    /**
+     * Load a new instance of a module.
+     *
+     * @param channel
+     * @param moduleName
+     * @param userAgent
+     * @param url top-level URL of the main page, null if using an old plugin
+     * @param tabKey opaque key of the tab, may be empty if the plugin can't
+     *     distinguish tabs or null if using an old plugin
+     * @param sessionKey opaque key for this session, null if using an old plugin
+     * @param userAgentIcon byte array containing an icon (which fits within
+     *     24x24) representing the user agent or null if unavailable
+     * @return a TreeLogger to use for the module's logs, or null if the module
+     *     load failed
+     */
+    public abstract TreeLogger loadModule(BrowserChannelServer channel,
+        String moduleName, String userAgent, String url, String tabKey,
+        String sessionKey, byte[] userAgentIcon);
+
+    public abstract ExceptionOrReturnValue setProperty(BrowserChannelServer channel,
+        int refId, int dispId, Value newValue);
+
+    public abstract void unloadModule(BrowserChannelServer channel, String moduleName);
+  }
 
   private static class ServerObjectRefFactory implements ObjectRefFactory {
 
@@ -71,7 +107,7 @@
   
   private static final Object cacheLock = new Object();
 
-  private final SessionHandler handler;
+  private final SessionHandlerServer handler;
 
   private final boolean ignoreRemoteDeath;
 
@@ -95,7 +131,7 @@
    * @throws IOException
    */
   public BrowserChannelServer(TreeLogger initialLogger, Socket socket,
-      SessionHandler handler, boolean ignoreRemoteDeath) throws IOException {
+      SessionHandlerServer handler, boolean ignoreRemoteDeath) throws IOException {
     super(socket, new ServerObjectRefFactory());
     this.handler = handler;
     this.ignoreRemoteDeath = ignoreRemoteDeath;
@@ -104,7 +140,7 @@
 
   // @VisibleForTesting
   BrowserChannelServer(TreeLogger initialLogger, InputStream inputStream,
-      OutputStream outputStream, SessionHandler handler,
+      OutputStream outputStream, SessionHandlerServer handler,
       boolean ignoreRemoteDeath) {
     super(inputStream, outputStream, new ServerObjectRefFactory());
     this.handler = handler;
@@ -141,6 +177,12 @@
     return protocolVersion;
   }
 
+  public ReturnMessage invoke(String methodName, Value vthis, Value[] vargs,
+      SessionHandlerServer handler) throws IOException, BrowserChannelException {
+    new InvokeOnClientMessage(this, methodName, vthis, vargs).send();
+    return reactToMessagesWhileWaitingForReturn(handler);
+  }
+
   /**
    * @param ccl
    * @param jsthis
@@ -217,6 +259,94 @@
     }
   }
 
+  /**
+   * React to messages from the other side, where no return value is expected.
+   * 
+   * @param handler
+   * @throws RemoteDeathError
+   */
+  public void reactToMessages(SessionHandlerServer handler) {
+    do {
+      try {
+        getStreamToOtherSide().flush();
+        MessageType messageType = Message.readMessageType(
+            getStreamFromOtherSide());
+        switch (messageType) {
+          case FREE_VALUE:
+            final FreeMessage freeMsg = FreeMessage.receive(this);
+            handler.freeValue(this, freeMsg.getIds());
+            break;
+          case INVOKE:
+            InvokeOnServerMessage imsg = InvokeOnServerMessage.receive(this);
+            ExceptionOrReturnValue result = handler.invoke(this, imsg.getThis(),
+                imsg.getMethodDispatchId(), imsg.getArgs());
+            sendFreedValues();
+            ReturnMessage.send(this, result);
+            break;
+          case INVOKE_SPECIAL:
+            handleInvokeSpecial(handler);
+            break;
+          case QUIT:
+            return;
+          default:
+            throw new RemoteDeathError(new BrowserChannelException(
+                "Invalid message type " + messageType));
+        }
+      } catch (IOException e) {
+        throw new RemoteDeathError(e);
+      } catch (BrowserChannelException e) {
+        throw new RemoteDeathError(e);
+      }
+    } while (true);
+  }
+
+  /**
+   * React to messages from the other side, where a return value is expected.
+   * 
+   * @param handler
+   * @throws BrowserChannelException 
+   * @throws RemoteDeathError
+   */
+  public ReturnMessage reactToMessagesWhileWaitingForReturn(
+      SessionHandlerServer handler) throws BrowserChannelException, RemoteDeathError {
+    do {
+      try {
+        getStreamToOtherSide().flush();
+        MessageType messageType = Message.readMessageType(
+            getStreamFromOtherSide());
+        switch (messageType) {
+          case FREE_VALUE:
+            final FreeMessage freeMsg = FreeMessage.receive(this);
+            handler.freeValue(this, freeMsg.getIds());
+            break;
+          case RETURN:
+            return ReturnMessage.receive(this);
+          case INVOKE:
+            InvokeOnServerMessage imsg = InvokeOnServerMessage.receive(this);
+            ExceptionOrReturnValue result = handler.invoke(this, imsg.getThis(),
+                imsg.getMethodDispatchId(), imsg.getArgs());
+            sendFreedValues();
+            ReturnMessage.send(this, result);
+            break;
+          case INVOKE_SPECIAL:
+            handleInvokeSpecial(handler);
+            break;
+          case QUIT:
+            // if we got an unexpected QUIT here, the remote plugin probably
+            // realized it was dying and had time to close the socket properly.
+            throw new RemoteDeathError(null);
+          default:
+            throw new BrowserChannelException("Invalid message type "
+                + messageType + " received waiting for return.");
+        }
+      } catch (IOException e) {
+        throw new RemoteDeathError(e);
+      } catch (BrowserChannelException e) {
+        throw new RemoteDeathError(e);
+      }
+    } while (true);
+  }
+
   public void run() {
     try {
       processConnection();
@@ -516,6 +646,28 @@
         "No alternate transports supported");
   }
 
+  private void handleInvokeSpecial(SessionHandlerServer handler) throws IOException,
+      BrowserChannelException {
+    final InvokeSpecialMessage ismsg = InvokeSpecialMessage.receive(this);
+    Value[] args = ismsg.getArgs();
+    ExceptionOrReturnValue retExc = null;
+    switch (ismsg.getDispatchId()) {
+      case GetProperty:
+        assert args.length == 2;
+        retExc = handler.getProperty(this, args[0].getInt(), args[1].getInt());
+        break;
+      case SetProperty:
+        assert args.length == 3;
+        retExc = handler.setProperty(this, args[0].getInt(), args[1].getInt(),
+            args[2]);
+        break;
+      default:
+        throw new HostedModeException("Unexpected InvokeSpecial method "
+            + ismsg.getDispatchId());
+    }
+    ReturnMessage.send(this, retExc);
+  }
+
   private void init(TreeLogger initialLogger) {
     this.logger = initialLogger;
     Thread thread = new Thread(this);
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java b/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java
index 02b10c4..284a0a8 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java
@@ -17,7 +17,7 @@
 
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.shell.BrowserChannel.SessionHandler;
+import com.google.gwt.dev.shell.BrowserChannelServer.SessionHandlerServer;
 
 import java.io.IOException;
 import java.net.BindException;
@@ -32,7 +32,6 @@
  */
 public class BrowserListener {
 
-
   /**
    * Get a query parameter to be added to the URL that specifies the address
    * of this listener.
@@ -59,7 +58,7 @@
    * @param handler 
    */
   public BrowserListener(final TreeLogger logger, String bindAddress,
-      int port, final SessionHandler handler) {
+      int port, final SessionHandlerServer handler) {
     try {
       listenSocket = new ServerSocket();
       listenSocket.setReuseAddress(true);
diff --git a/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java b/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java
index a2a415c..987ca66 100644
--- a/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java
+++ b/dev/core/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java
@@ -18,9 +18,9 @@
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.dev.shell.BrowserChannel.JavaObjectRef;
 import com.google.gwt.dev.shell.BrowserChannel.JsObjectRef;
-import com.google.gwt.dev.shell.BrowserChannel.SessionHandler;
 import com.google.gwt.dev.shell.BrowserChannel.Value;
 import com.google.gwt.dev.shell.BrowserChannel.Value.ValueType;
+import com.google.gwt.dev.shell.BrowserChannelClient.SessionHandlerClient;
 import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
 
 import com.gargoylesoftware.htmlunit.ScriptResult;
@@ -37,16 +37,13 @@
 import net.sourceforge.htmlunit.corejs.javascript.Undefined;
 
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.Map;
-import java.util.Set;
 
 /**
- * Handle session tasks for HtmlUnit. TODO (amitmanjhi): refactor
- * SessionHandler.
+ * Handle session tasks for HtmlUnit.
  */
-public class HtmlUnitSessionHandler extends SessionHandler {
+public class HtmlUnitSessionHandler extends SessionHandlerClient {
 
   private class ToStringMethod extends ScriptableObject implements Function {
 
@@ -93,17 +90,14 @@
    * The htmlPage is also used to synchronize calls to Java code.
    */
   private HtmlPage htmlPage;
-  private Set<Integer> javaObjectsToFree;
-
   private JavaScriptEngine jsEngine;
-
   private IdentityHashMap<Scriptable, Integer> jsObjectToRef;
-  private final PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
-
-  private int nextRefId = 1;
+  private int nextRefId;
   private Map<Integer, Scriptable> refToJsObject;
   private SessionData sessionData;
 
+  private final PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
+
   private final ToStringMethod toStringMethod = new ToStringMethod();
 
   private final Window window;
@@ -117,7 +111,6 @@
         + htmlPage);
 
     jsObjectToRef = new IdentityHashMap<Scriptable, Integer>();
-    javaObjectsToFree = new HashSet<Integer>();
     nextRefId = 1;
     refToJsObject = new HashMap<Integer, Scriptable>();
 
@@ -126,7 +119,7 @@
   }
 
   @Override
-  public void freeValue(BrowserChannel channel, int[] ids) {
+  public void freeValue(BrowserChannelClient channel, int[] ids) {
     for (int id : ids) {
       Scriptable scriptable = refToJsObject.remove(id);
       if (scriptable != null) {
@@ -135,10 +128,6 @@
     }
   }
 
-  public HtmlPage getHtmlPage() {
-    return htmlPage;
-  }
-
   public JavaObject getOrCreateJavaObject(int refId, Context context) {
     JavaObject javaObject = javaObjectCache.get(refId);
     if (javaObject == null) {
@@ -148,30 +137,22 @@
     return javaObject;
   }
 
-  @Override
-  public ExceptionOrReturnValue getProperty(BrowserChannel channel, int refId,
-      int dispId) {
-    throw new UnsupportedOperationException(
-        "getProperty should not be called on the client-side");
+  public HtmlPage getSynchronizationObject() {
+    return htmlPage;
   }
 
   public Object getToStringTearOff(Context jsContext) {
     return toStringMethod;
   }
 
+  @Override
   public String getUserAgent() {
     return "HtmlUnit-"
         + jsEngine.getWebClient().getBrowserVersion().getUserAgent();
   }
 
   @Override
-  public ExceptionOrReturnValue invoke(BrowserChannel channel, Value thisObj,
-      int dispId, Value[] args) {
-    throw new UnsupportedOperationException(
-        "should not be called on the client side");
-  }
-
-  public ExceptionOrReturnValue invoke(BrowserChannel channel, Value thisObj,
+  public ExceptionOrReturnValue invoke(BrowserChannelClient channel, Value thisObj,
       String methodName, Value[] args) {
     logger.log(TreeLogger.DEBUG, "INVOKE: thisObj: " + thisObj
         + ", methodName: " + methodName + ", args: " + args);
@@ -236,26 +217,13 @@
         result));
   }
 
-  @SuppressWarnings("unused")
-  public ExceptionOrReturnValue invokeSpecial(BrowserChannel channel,
-      SpecialDispatchId specialDispatchId, Value[] args) {
-    throw new UnsupportedOperationException(
-        "InvokeSpecial must not be called on the client side");
-  }
-
-  public void loadJsni(BrowserChannel channel, String jsniString) {
+  @Override
+  public void loadJsni(BrowserChannelClient channel, String jsniString) {
     logger.log(TreeLogger.SPAM, "LOAD_JSNI: " + jsniString);
     ScriptResult scriptResult = htmlPage.executeJavaScript(jsniString);
     logger.log(TreeLogger.INFO, "LOAD_JSNI: scriptResult=" + scriptResult);
   }
 
-  @Override
-  public TreeLogger loadModule(BrowserChannel channel, String moduleName,
-      String userAgent, String url, String tabKey, String sessionKey,
-      byte[] userAgentIcon) {
-    throw new UnsupportedOperationException("loadModule must not be called");
-  }
-
   public Value makeValueFromJsval(Context jsContext, Object value) {
     if (value == Undefined.instance) {
       return new Value();
@@ -291,38 +259,10 @@
     return new Value(value);
   }
 
-  // TODO: check synchronization and multi-threading
-  public void sendFreeValues(BrowserChannel channel) {
-    int size = javaObjectsToFree.size();
-    if (size == 0) {
-      return;
-    }
-    int ids[] = new int[size];
-    int index = 0;
-    for (int id : javaObjectsToFree) {
-      ids[index++] = id;
-    }
-    if (ServerMethods.freeJava(channel, this, ids)) {
-      javaObjectsToFree.clear();
-    }
-  }
-
-  @Override
-  public ExceptionOrReturnValue setProperty(BrowserChannel channel, int refId,
-      int dispId, Value newValue) {
-    throw new UnsupportedOperationException(
-        "setProperty should not be called on the client-side");
-  }
-
   public void setSessionData(SessionData sessionData) {
     this.sessionData = sessionData;
   }
 
-  @Override
-  public void unloadModule(BrowserChannel channel, String moduleName) {
-    throw new UnsupportedOperationException("unloadModule must not be called");
-  }
-
   /*
    * Returning java objects works. No need to return NativeNumber, NativeString,
    * NativeBoolean, or Undefined.
@@ -370,5 +310,4 @@
     }
     return currentUrl;
   }
-
 }
diff --git a/dev/core/src/com/google/gwt/dev/shell/JavaObject.java b/dev/core/src/com/google/gwt/dev/shell/JavaObject.java
index c66d285..9a4a0ea 100644
--- a/dev/core/src/com/google/gwt/dev/shell/JavaObject.java
+++ b/dev/core/src/com/google/gwt/dev/shell/JavaObject.java
@@ -45,17 +45,17 @@
   }
 
   static ExceptionOrReturnValue getReturnFromJavaMethod(Context cx,
-      HtmlUnitSessionHandler sessionHandler, BrowserChannel channel,
+      HtmlUnitSessionHandler sessionHandler, BrowserChannelClient channel,
       int dispatchId, Value thisValue, Value valueArgs[]) {
 
-    synchronized (sessionHandler.getHtmlPage()) {
+    synchronized (sessionHandler.getSynchronizationObject()) {
       try {
         new InvokeOnServerMessage(channel, dispatchId, thisValue, valueArgs).send();
       } catch (IOException e) {
         return DEFAULT_VALUE;
       }
       try {
-        ReturnMessage returnMessage = ((BrowserChannelClient) channel).reactToMessagesWhileWaitingForReturn(sessionHandler);
+        ReturnMessage returnMessage = channel.reactToMessagesWhileWaitingForReturn(sessionHandler);
         return new ExceptionOrReturnValue(returnMessage.isException(),
             returnMessage.getReturnValue());
       } catch (IOException e) {
diff --git a/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java b/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java
index 65c6120..243185c 100644
--- a/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java
+++ b/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java
@@ -17,8 +17,8 @@
 
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.dev.ModuleHandle;
-import com.google.gwt.dev.shell.BrowserChannel.SessionHandler;
 import com.google.gwt.dev.shell.BrowserChannel.Value;
+import com.google.gwt.dev.shell.BrowserChannelServer.SessionHandlerServer;
 import com.google.gwt.dev.shell.JsValue.DispatchMethod;
 import com.google.gwt.dev.shell.JsValue.DispatchObject;
 import com.google.gwt.dev.util.PerfLogger;
@@ -31,7 +31,7 @@
 /**
  * 
  */
-public class OophmSessionHandler extends SessionHandler {
+public class OophmSessionHandler extends SessionHandlerServer {
 
   private BrowserWidgetHost host;
 
@@ -53,23 +53,21 @@
   }
 
   @Override
-  public void freeValue(BrowserChannel channel, int[] ids) {
-    BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
-    ServerObjectsTable localObjects = serverChannel.getJavaObjectsExposedInBrowser();
+  public void freeValue(BrowserChannelServer channel, int[] ids) {
+    ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
     for (int id : ids) {
       localObjects.free(id);
     }
   }
 
   @Override
-  public ExceptionOrReturnValue getProperty(BrowserChannel channel, int refId,
+  public ExceptionOrReturnValue getProperty(BrowserChannelServer channel, int refId,
       int dispId) {
-    BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
-    ModuleSpace moduleSpace = moduleMap.get(serverChannel);
-    ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
+    ModuleSpace moduleSpace = moduleMap.get(channel);
+    ModuleHandle moduleHandle = moduleHandleMap.get(channel);
     assert moduleSpace != null && moduleHandle != null;
     TreeLogger logger = moduleHandle.getLogger();
-    ServerObjectsTable localObjects = serverChannel.getJavaObjectsExposedInBrowser();
+    ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
     try {
       JsValueOOPHM obj = new JsValueOOPHM();
       DispatchObject dispObj;
@@ -81,14 +79,14 @@
               + ccl.getClassInfoByDispId(dispId).getMember(dispId) + "]) on "
               + obj.toString(), null);
       JsValueOOPHM jsval = (JsValueOOPHM) dispObj.getField(dispId);
-      Value retVal = serverChannel.convertFromJsValue(localObjects, jsval);
+      Value retVal = channel.convertFromJsValue(localObjects, jsval);
       branch.log(TreeLogger.SPAM, "result is " + retVal, null);
       return new ExceptionOrReturnValue(false, retVal);
     } catch (Throwable t) {
       JsValueOOPHM jsval = new JsValueOOPHM();
       JsValueGlue.set(jsval, moduleSpace.getIsolatedClassLoader(),
           t.getClass(), t);
-      Value retVal = serverChannel.convertFromJsValue(localObjects, jsval);
+      Value retVal = channel.convertFromJsValue(localObjects, jsval);
       return new ExceptionOrReturnValue(true, retVal);
     }
   }
@@ -97,12 +95,11 @@
    * Invoke a method on a server object in from client code.
    */
   @Override
-  public ExceptionOrReturnValue invoke(BrowserChannel channel, Value thisVal,
+  public ExceptionOrReturnValue invoke(BrowserChannelServer channel, Value thisVal,
       int methodDispatchId, Value[] args) {
-    BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
-    ServerObjectsTable localObjects = serverChannel.getJavaObjectsExposedInBrowser();
-    ModuleSpace moduleSpace = moduleMap.get(serverChannel);
-    ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
+    ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
+    ModuleSpace moduleSpace = moduleMap.get(channel);
+    ModuleHandle moduleHandle = moduleHandleMap.get(channel);
     assert moduleSpace != null && moduleHandle != null;
     TreeLogger logger = moduleHandle.getLogger();
     CompilingClassLoader cl = moduleSpace.getIsolatedClassLoader();
@@ -113,7 +110,7 @@
     }
 
     JsValueOOPHM jsThis = new JsValueOOPHM();
-    serverChannel.convertToJsValue(cl, localObjects, thisVal, jsThis);
+    channel.convertToJsValue(cl, localObjects, thisVal, jsThis);
 
     TreeLogger branch = TreeLogger.NULL;
     if (logger.isLoggable(TreeLogger.SPAM)) {
@@ -136,7 +133,7 @@
     JsValueOOPHM[] jsArgs = new JsValueOOPHM[args.length];
     for (int i = 0; i < args.length; ++i) {
       jsArgs[i] = new JsValueOOPHM();
-      serverChannel.convertToJsValue(cl, localObjects, args[i], jsArgs[i]);
+      channel.convertToJsValue(cl, localObjects, args[i], jsArgs[i]);
       branch.log(TreeLogger.SPAM, " arg " + i + " = " + jsArgs[i].toString(),
           null);
     }
@@ -160,27 +157,26 @@
       JsValueGlue.set(jsRetVal, moduleSpace.getIsolatedClassLoader(),
           t.getClass(), t);
     }
-    Value retVal = serverChannel.convertFromJsValue(localObjects, jsRetVal);
+    Value retVal = channel.convertFromJsValue(localObjects, jsRetVal);
     return new ExceptionOrReturnValue(exception, retVal);
   }
 
   @Override
-  public synchronized TreeLogger loadModule(BrowserChannel channel,
+  public synchronized TreeLogger loadModule(BrowserChannelServer channel,
       String moduleName, String userAgent, String url, String tabKey,
       String sessionKey, byte[] userAgentIcon) {
     PerfLogger.start("OophmSessionHandler.loadModule " + moduleName);
-    BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
     ModuleHandle moduleHandle = host.createModuleLogger(moduleName, userAgent,
-        url, tabKey, sessionKey, serverChannel, userAgentIcon);
+        url, tabKey, sessionKey, channel, userAgentIcon);
     TreeLogger logger = moduleHandle.getLogger();
-    moduleHandleMap.put(serverChannel, moduleHandle);
+    moduleHandleMap.put(channel, moduleHandle);
     ModuleSpace moduleSpace = null;
     try {
       // Attach a new ModuleSpace to make it programmable.
       ModuleSpaceHost msh = host.createModuleSpaceHost(moduleHandle,
           moduleName);
-      moduleSpace = new ModuleSpaceOOPHM(msh, moduleName, serverChannel);
-      moduleMap.put(serverChannel, moduleSpace);
+      moduleSpace = new ModuleSpaceOOPHM(msh, moduleName, channel);
+      moduleMap.put(channel, moduleSpace);
       PerfLogger.start("ModuleSpace.onLoad");
       moduleSpace.onLoad(logger);
       moduleHandle.getLogger().log(TreeLogger.INFO,
@@ -197,8 +193,8 @@
         moduleSpace.dispose();        
       }
       moduleHandle.unload();
-      moduleMap.remove(serverChannel);
-      moduleHandleMap.remove(serverChannel);
+      moduleMap.remove(channel);
+      moduleHandleMap.remove(channel);
       return null;
     } finally {
       PerfLogger.end();
@@ -208,14 +204,13 @@
   }
 
   @Override
-  public ExceptionOrReturnValue setProperty(BrowserChannel channel, int refId,
+  public ExceptionOrReturnValue setProperty(BrowserChannelServer channel, int refId,
       int dispId, Value newValue) {
-    BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
-    ModuleSpace moduleSpace = moduleMap.get(serverChannel);
-    ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
+    ModuleSpace moduleSpace = moduleMap.get(channel);
+    ModuleHandle moduleHandle = moduleHandleMap.get(channel);
     assert moduleSpace != null && moduleHandle != null;
     TreeLogger logger = moduleHandle.getLogger();
-    ServerObjectsTable localObjects = serverChannel.getJavaObjectsExposedInBrowser();
+    ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
     try {
       JsValueOOPHM obj = new JsValueOOPHM();
       DispatchObject dispObj;
@@ -225,7 +220,7 @@
       logger.log(TreeLogger.SPAM, "Client special invoke of setProperty(id="
           + dispId + ", newValue=" + newValue + ") on " + obj.toString(), null);
       JsValueOOPHM jsval = new JsValueOOPHM();
-      serverChannel.convertToJsValue(moduleSpace.getIsolatedClassLoader(),
+      channel.convertToJsValue(moduleSpace.getIsolatedClassLoader(),
           localObjects, newValue, jsval);
       dispObj.setField(dispId, jsval);
       return new ExceptionOrReturnValue(false, newValue);
@@ -233,16 +228,15 @@
       JsValueOOPHM jsval = new JsValueOOPHM();
       JsValueGlue.set(jsval, moduleSpace.getIsolatedClassLoader(),
           t.getClass(), t);
-      Value retVal = serverChannel.convertFromJsValue(localObjects, jsval);
+      Value retVal = channel.convertFromJsValue(localObjects, jsval);
       return new ExceptionOrReturnValue(true, retVal);
     }
   }
 
   @Override
-  public void unloadModule(BrowserChannel channel, String moduleName) {
-    BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
-    ModuleHandle moduleHandle = moduleHandleMap.get(serverChannel);
-    ModuleSpace moduleSpace = moduleMap.get(serverChannel);
+  public void unloadModule(BrowserChannelServer channel, String moduleName) {
+    ModuleHandle moduleHandle = moduleHandleMap.get(channel);
+    ModuleSpace moduleSpace = moduleMap.get(channel);
     if (moduleSpace == null || moduleHandle == null) {
       topLogger.log(TreeLogger.ERROR, "Unload request without a module loaded",
           null);
@@ -254,7 +248,7 @@
             + ")", null);
     moduleSpace.dispose();
     moduleHandle.unload();
-    moduleMap.remove(serverChannel);
-    moduleHandleMap.remove(serverChannel);
+    moduleMap.remove(channel);
+    moduleHandleMap.remove(channel);
   }
 }
diff --git a/dev/core/src/com/google/gwt/dev/shell/ServerMethods.java b/dev/core/src/com/google/gwt/dev/shell/ServerMethods.java
index e1051d3..d342874 100644
--- a/dev/core/src/com/google/gwt/dev/shell/ServerMethods.java
+++ b/dev/core/src/com/google/gwt/dev/shell/ServerMethods.java
@@ -20,6 +20,7 @@
 import com.google.gwt.dev.shell.BrowserChannel.ReturnMessage;
 import com.google.gwt.dev.shell.BrowserChannel.Value;
 import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.SpecialDispatchId;
+import com.google.gwt.dev.shell.BrowserChannelClient.SessionHandlerClient;
 
 import java.io.IOException;
 
@@ -34,9 +35,9 @@
    * @param ids ID of object to free
    * @return false if an error occurred
    */
-  static boolean freeJava(BrowserChannel channel,
-      HtmlUnitSessionHandler handler, int ids[]) {
-    if (!((BrowserChannelClient) channel).isConnected()) {
+  static boolean freeJava(BrowserChannelClient channel,
+      SessionHandlerClient handler, int ids[]) {
+    if (!channel.isConnected()) {
       // ignoring freeJava after disconnect.
       return true;
     }
@@ -55,9 +56,9 @@
    * @param dispatchId dispatch ID of field
    * @return the value of the property, undef if none (or on error)
    */
-  static Value getProperty(BrowserChannel channel,
-      HtmlUnitSessionHandler handler, int objectRef, int dispatchId) {
-    if (!((BrowserChannelClient) channel).isConnected()) {
+  static Value getProperty(BrowserChannelClient channel,
+      SessionHandlerClient handler, int objectRef, int dispatchId) {
+    if (!channel.isConnected()) {
       // ignoring getProperty() after disconnect
       return new Value();
     }
@@ -67,11 +68,10 @@
     args[1] = new Value();
     args[1].setInt(dispatchId);
 
-    synchronized (handler.getHtmlPage()) {
+    synchronized (handler.getSynchronizationObject()) {
       try {
         new InvokeSpecialMessage(channel, SpecialDispatchId.GetProperty, args).send();
-        // TODO: refactor in order to remove cast.
-        ReturnMessage returnMessage = ((BrowserChannelClient) channel).reactToMessagesWhileWaitingForReturn(handler);
+        ReturnMessage returnMessage = channel.reactToMessagesWhileWaitingForReturn(handler);
         if (!returnMessage.isException()) {
           return returnMessage.getReturnValue();
         }
@@ -90,8 +90,8 @@
    * @param value value to store in the property
    * @return false if an error occurred
    */
-  static boolean setProperty(BrowserChannel channel,
-      HtmlUnitSessionHandler handler, int objectRef, int dispatchId, Value value) {
+  static boolean setProperty(BrowserChannelClient channel,
+      SessionHandlerClient handler, int objectRef, int dispatchId, Value value) {
     Value args[] = new Value[3];
     for (int i = 0; i < args.length; i++) {
       args[i] = new Value();
@@ -99,10 +99,10 @@
     args[0].setInt(objectRef);
     args[1].setInt(dispatchId);
     args[2] = value;
-    synchronized (handler.getHtmlPage()) {
+    synchronized (handler.getSynchronizationObject()) {
       try {
         new InvokeSpecialMessage(channel, SpecialDispatchId.SetProperty, args).send();
-        ReturnMessage returnMessage = ((BrowserChannelClient) channel).reactToMessagesWhileWaitingForReturn(handler);
+        ReturnMessage returnMessage = channel.reactToMessagesWhileWaitingForReturn(handler);
         if (!returnMessage.isException()) {
           return true;
         }
diff --git a/dev/core/src/com/google/gwt/dev/shell/SessionData.java b/dev/core/src/com/google/gwt/dev/shell/SessionData.java
index 82281c3..8f04d27 100644
--- a/dev/core/src/com/google/gwt/dev/shell/SessionData.java
+++ b/dev/core/src/com/google/gwt/dev/shell/SessionData.java
@@ -19,20 +19,19 @@
  * A class to encapsulate data needed by {@code JavaObject}.
  */
 public class SessionData {
-  private final BrowserChannel browserChannel;
+  private final BrowserChannelClient browserChannel;
   private final HtmlUnitSessionHandler sessionHandler;
   
-  public SessionData(HtmlUnitSessionHandler sessionHandler, BrowserChannel browserChannel) {
+  public SessionData(HtmlUnitSessionHandler sessionHandler, BrowserChannelClient browserChannel) {
     this.sessionHandler = sessionHandler;
     this.browserChannel = browserChannel;
   }
 
-  public BrowserChannel getChannel() {
+  public BrowserChannelClient getChannel() {
     return browserChannel;
   }
 
   public HtmlUnitSessionHandler getSessionHandler() {
     return sessionHandler;
   }
-  
 }
diff --git a/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java b/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java
index d981c37..eb90b23 100644
--- a/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java
+++ b/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java
@@ -24,9 +24,9 @@
 import com.google.gwt.dev.shell.BrowserChannel.QuitMessage;
 import com.google.gwt.dev.shell.BrowserChannel.RequestIconMessage;
 import com.google.gwt.dev.shell.BrowserChannel.ReturnMessage;
-import com.google.gwt.dev.shell.BrowserChannel.SessionHandler;
 import com.google.gwt.dev.shell.BrowserChannel.UserAgentIconMessage;
 import com.google.gwt.dev.shell.BrowserChannel.Value;
+import com.google.gwt.dev.shell.BrowserChannelServer.SessionHandlerServer;
 
 import junit.framework.TestCase;
 
@@ -52,7 +52,7 @@
 
     public TestBrowserChannelServer(TreeLogger logger,
         InputStream inputStream, OutputStream outputStream,
-        SessionHandler handler) throws IOException {
+        SessionHandlerServer handler) {
       super(logger, inputStream, outputStream, handler, true);
     }
 
@@ -101,7 +101,7 @@
    * A SessionHandler which keeps track of parameters from the LoadModule
    * message, but mocks out everything else.
    */
-  private static class TestSessionHandler extends SessionHandler {
+  private static class TestSessionHandler extends SessionHandlerServer {
 
     private String loadedModule;
     private String userAgent;
@@ -112,7 +112,7 @@
     private String moduleName;
 
     @Override
-    public void freeValue(BrowserChannel channel, int[] ids) {
+    public void freeValue(BrowserChannelServer channel, int[] ids) {
     }
 
     public String getLoadedModule() {
@@ -124,7 +124,7 @@
     }
 
     @Override
-    public ExceptionOrReturnValue getProperty(BrowserChannel channel,
+    public ExceptionOrReturnValue getProperty(BrowserChannelServer channel,
         int refId, int dispId) {
       return new ExceptionOrReturnValue(false, new Value());
     }
@@ -150,13 +150,13 @@
     }
 
     @Override
-    public ExceptionOrReturnValue invoke(BrowserChannel channel, Value thisObj,
+    public ExceptionOrReturnValue invoke(BrowserChannelServer channel, Value thisObj,
         int dispId, Value[] args) {
       return new ExceptionOrReturnValue(false, new Value());
     }
 
     @Override
-    public TreeLogger loadModule(BrowserChannel channel, String moduleName,
+    public TreeLogger loadModule(BrowserChannelServer channel, String moduleName,
         String userAgent, String url, String tabKey, String sessionKey,
         byte[] userAgentIcon) {
       loadedModule = moduleName;
@@ -170,13 +170,13 @@
     }
 
     @Override
-    public ExceptionOrReturnValue setProperty(BrowserChannel channel,
+    public ExceptionOrReturnValue setProperty(BrowserChannelServer channel,
         int refId, int dispId, Value newValue) {
       return new ExceptionOrReturnValue(false, new Value());
     }
 
     @Override
-    public void unloadModule(BrowserChannel channel, String moduleName) {
+    public void unloadModule(BrowserChannelServer channel, String moduleName) {
       loadedModule = null;
     }   
   }