Merged new Chromium Dev Tools version with the repository head
authorEugene Ostroukhov <eugeneo@symbian.org>
Wed, 27 Jan 2010 15:59:22 -0800
changeset 53 ba7c1ce1cc4a
parent 52 f577ea64429e (diff)
parent 51 a0e2f1f4e212 (current diff)
child 54 5a2cfa9bc743
Merged new Chromium Dev Tools version with the repository head
org.symbian.tools.wrttools/.classpath
org.symbian.tools.wrttools/build.properties
org.symbian.tools.wrttools/icons/Thumbs.db
--- a/org.chromium.debug.core/META-INF/MANIFEST.MF	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/META-INF/MANIFEST.MF	Wed Jan 27 15:59:22 2010 -0800
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.chromium.debug.core;singleton:=true
-Bundle-Version: 0.1.3.qualifier
+Bundle-Version: 0.1.5.qualifier
 Bundle-Activator: org.chromium.debug.core.ChromiumDebugPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
@@ -12,7 +12,7 @@
  org.eclipse.ui;bundle-version="3.4.1",
  org.eclipse.jface.text;bundle-version="3.4.1",
  org.eclipse.ui.workbench.texteditor;bundle-version="3.4.1",
- org.chromium.sdk;bundle-version="0.1.3"
+ org.chromium.sdk;bundle-version="0.1.5"
 Bundle-ActivationPolicy: lazy
 Bundle-ClassPath: bin/,
  .
--- a/org.chromium.debug.core/src/org/chromium/debug/core/ChromiumDebugPlugin.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/ChromiumDebugPlugin.java	Wed Jan 27 15:59:22 2010 -0800
@@ -24,9 +24,6 @@
   /** The plug-in ID. */
   public static final String PLUGIN_ID = "org.chromium.debug.core"; //$NON-NLS-1$
 
-  /** The debug model ID. */
-  public static final String DEBUG_MODEL_ID = "org.chromium.debug"; //$NON-NLS-1$
-
   /** The JavaScript line breakpoint marker. */
   public static final String BP_MARKER = PLUGIN_ID + ".LineBP"; //$NON-NLS-1$
 
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/ArrayValue.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/ArrayValue.java	Wed Jan 27 15:59:22 2010 -0800
@@ -22,7 +22,7 @@
 
   private final IVariable[] elements;
 
-  public ArrayValue(IChromiumDebugTarget debugTarget, JsArray array) {
+  public ArrayValue(DebugTargetImpl debugTarget, JsArray array) {
     super(debugTarget, array);
     this.elements = createElements();
   }
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/BreakpointAdapterFactory.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/BreakpointAdapterFactory.java	Wed Jan 27 15:59:22 2010 -0800
@@ -24,7 +24,7 @@
       if (resource != null) {
         String extension = resource.getFileExtension();
         if (extension != null && ChromiumDebugPluginUtil.CHROMIUM_EXTENSION.equals(extension)) {
-          return new LineBreakpointAdapter();
+          return new LineBreakpointAdapter.ForVirtualProject();
         }
       }
     }
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/ChromiumLineBreakpoint.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/ChromiumLineBreakpoint.java	Wed Jan 27 15:59:22 2010 -0800
@@ -104,7 +104,7 @@
   }
 
   public String getModelIdentifier() {
-    return ChromiumDebugPlugin.DEBUG_MODEL_ID;
+    return VProjectWorkspaceBridge.DEBUG_MODEL_ID;
   }
 
   public void changed() {
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/ConnectionLoggerImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/ConnectionLoggerImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -5,10 +5,10 @@
 package org.chromium.debug.core.model;
 
 import java.io.IOException;
-import java.io.Reader;
 import java.io.Writer;
 
 import org.chromium.sdk.ConnectionLogger;
+import org.chromium.sdk.LineReader;
 import org.eclipse.debug.core.DebugPlugin;
 import org.eclipse.debug.core.model.ITerminate;
 
@@ -46,45 +46,83 @@
     this.lifecycleListener = lifecycleListener;
   }
 
-  public Writer wrapWriter(final Writer streamWriter) {
-    return new Writer() {
+  /**
+   * We mix 2 streams into a single console. This type helps to annotate them textually.
+   */
+  private interface StreamId {
+    String getStreamName();
+  }
+
+  public LoggableWriter wrapWriter(final LoggableWriter originalLoggableWriter) {
+    final StreamId streamId = new StreamId() {
+      public String getStreamName() {
+        return Messages.ConnectionLoggerImpl_SentToChrome;
+      }
+    };
+    final Writer originalWriter = originalLoggableWriter.getWriter();
+    final Writer wrappedWriter = new Writer() {
       @Override
       public void close() throws IOException {
-        streamWriter.close();
+        originalWriter.close();
         flushLogWriter();
       }
       @Override
       public void flush() throws IOException {
-        streamWriter.flush();
+        originalWriter.flush();
         flushLogWriter();
       }
       @Override
       public void write(char[] cbuf, int off, int len) throws IOException {
-        streamWriter.write(cbuf, off, len);
-
-        writeToLog(cbuf, off, len, this,
-            Messages.ConnectionLoggerImpl_SentToChrome);
+        originalWriter.write(cbuf, off, len);
+        writeToLog(cbuf, off, len, streamId);
+      }
+    };
+    return new LoggableWriter() {
+      public Writer getWriter() {
+        return wrappedWriter;
+      }
+      public void markSeparatorForLog() {
+        writeToLog(MESSAGE_SEPARATOR, streamId);
+        flushLogWriter();
       }
     };
   }
-  public Reader wrapReader(final Reader streamReader) {
-    return new Reader() {
-      @Override
-      public void close() throws IOException {
-        streamReader.close();
-        flushLogWriter();
+
+  public LoggableReader wrapReader(final LoggableReader loggableReader) {
+    final StreamId streamId = new StreamId() {
+      public String getStreamName() {
+        return Messages.ConnectionLoggerImpl_ReceivedFromChrome;
       }
-
-      @Override
+    };
+    final LineReader streamReader = loggableReader.getReader();
+    final LineReader wrappedReader = new LineReader() {
       public int read(char[] cbuf, int off, int len) throws IOException {
         int res = streamReader.read(cbuf, off, len);
         if (res > 0) {
-          writeToLog(cbuf, off, res, this,
-              Messages.ConnectionLoggerImpl_ReceivedFromChrome);
+          writeToLog(cbuf, off, res, streamId);
           flushLogWriter();
         }
         return res;
       }
+
+      public String readLine() throws IOException {
+        String res = streamReader.readLine();
+        if (res != null) {
+          writeToLog(res + '\n', streamId);
+          flushLogWriter();
+        }
+        return res;
+      }
+    };
+    return new LoggableReader() {
+      public LineReader getReader() {
+        return wrappedReader;
+      }
+
+      public void markSeparatorForLog() {
+        writeToLog(MESSAGE_SEPARATOR, streamId);
+        flushLogWriter();
+      }
     };
   }
 
@@ -105,21 +143,31 @@
     this.connectionCloser = connectionCloser;
   }
 
-  private synchronized void writeToLog(char[] cbuf, int off, int len, Object source,
-      String sourceName) {
+  private synchronized void writeToLog(String str, StreamId streamId) {
     try {
-      if (lastSource != source) {
-        if (lastSource != null) {
-          logWriter.append('\n');
-        }
-        logWriter.append("> ").append(sourceName).append('\n'); //$NON-NLS-1$
-        lastSource = source;
-      }
+      printHead(streamId);
+      logWriter.append(str);
+    } catch (IOException e) {
+      DebugPlugin.log(e);
+    }
+  }
+  private synchronized void writeToLog(char[] cbuf, int off, int len, StreamId streamId) {
+    try {
+      printHead(streamId);
       logWriter.write(cbuf, off, len);
     } catch (IOException e) {
       DebugPlugin.log(e);
     }
   }
+  private void printHead(StreamId streamId) throws IOException {
+    if (lastSource != streamId) {
+      if (lastSource != null) {
+        logWriter.append('\n');
+      }
+      logWriter.append("> ").append(streamId.getStreamName()).append('\n'); //$NON-NLS-1$
+      lastSource = streamId;
+    }
+  }
   private void flushLogWriter() {
     try {
       logWriter.flush();
@@ -130,7 +178,7 @@
 
   private final Writer logWriter;
   private final LogLifecycleListener lifecycleListener;
-  private Object lastSource = null;
+  private StreamId lastSource = null;
   private volatile ConnectionCloser connectionCloser = null;
   private volatile boolean isClosed = false;
 
@@ -151,4 +199,6 @@
       connectionCloser0.closeConnection();
     }
   };
+
+  private static final String MESSAGE_SEPARATOR = Messages.ConnectionLoggerImpl_MessageSeparator;
 }
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/DebugElementImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/DebugElementImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -4,7 +4,6 @@
 
 package org.chromium.debug.core.model;
 
-import org.chromium.debug.core.ChromiumDebugPlugin;
 import org.eclipse.core.runtime.PlatformObject;
 import org.eclipse.debug.core.ILaunch;
 import org.eclipse.debug.core.model.IDebugElement;
@@ -14,13 +13,17 @@
  */
 public class DebugElementImpl extends PlatformObject implements IDebugElement {
 
-  private final IChromiumDebugTarget debugTarget;
+  /**
+   * Instance of {@link DebugTargetImpl} or {@code null} if this is {@link DebugTargetImpl}.
+   * TODO(peter.rybin): Do we really need this null value?
+   */
+  private final DebugTargetImpl debugTarget;
 
-  public DebugElementImpl(IChromiumDebugTarget debugTarget) {
+  public DebugElementImpl(DebugTargetImpl debugTarget) {
     this.debugTarget = debugTarget;
   }
 
-  public IChromiumDebugTarget getDebugTarget() {
+  public DebugTargetImpl getDebugTarget() {
     return debugTarget;
   }
 
@@ -29,7 +32,7 @@
   }
 
   public String getModelIdentifier() {
-    return ChromiumDebugPlugin.DEBUG_MODEL_ID;
+    return getDebugTarget().getChromiumModelIdentifier();
   }
 
   @Override
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/DebugTargetImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/DebugTargetImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -4,11 +4,7 @@
 
 package org.chromium.debug.core.model;
 
-import java.util.Collection;
-
 import org.chromium.debug.core.ChromiumDebugPlugin;
-import org.chromium.debug.core.util.ChromiumDebugPluginUtil;
-import org.chromium.sdk.Breakpoint;
 import org.chromium.sdk.CallFrame;
 import org.chromium.sdk.DebugContext;
 import org.chromium.sdk.DebugEventListener;
@@ -17,11 +13,8 @@
 import org.chromium.sdk.Script;
 import org.chromium.sdk.DebugContext.State;
 import org.chromium.sdk.DebugContext.StepAction;
-import org.chromium.sdk.JavascriptVm.BreakpointCallback;
-import org.chromium.sdk.JavascriptVm.ScriptsCallback;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IMarkerDelta;
-import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
@@ -30,47 +23,43 @@
 import org.eclipse.debug.core.DebugEvent;
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.debug.core.DebugPlugin;
-import org.eclipse.debug.core.IBreakpointManager;
 import org.eclipse.debug.core.ILaunch;
 import org.eclipse.debug.core.ILaunchListener;
 import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IDebugTarget;
 import org.eclipse.debug.core.model.IMemoryBlock;
 import org.eclipse.debug.core.model.IProcess;
-import org.eclipse.debug.core.model.ISourceLocator;
-import org.eclipse.debug.core.model.IStackFrame;
 import org.eclipse.debug.core.model.IThread;
 
 /**
  * An IDebugTarget implementation for remote JavaScript debugging.
  * Can debug any target that supports the ChromeDevTools protocol.
  */
-public class DebugTargetImpl extends DebugElementImpl implements IChromiumDebugTarget {
+public class DebugTargetImpl extends DebugElementImpl implements IDebugTarget {
 
   private static final IThread[] EMPTY_THREADS = new IThread[0];
 
-  private static final long OPERATION_TIMEOUT_MS = 15000L;
-
   private final ILaunch launch;
 
   private final JavascriptThread[] threads;
 
   private JavascriptVmEmbedder vmEmbedder = STUB_VM_EMBEDDER;
 
-  private ResourceManager resourceManager;
-
-  private BreakpointRegistry breakpointRegistry;
-
-  private IProject debugProject = null;
-
-  private DebugContext debugContext;
+  private volatile DebugContext debugContext;
 
   private boolean isSuspended = false;
 
   private boolean isDisconnected = false;
 
+  private final WorkspaceBridge.Factory workspaceBridgeFactory;
 
-  public DebugTargetImpl(ILaunch launch) {
+  private WorkspaceBridge workspaceRelations = null;
+
+  private final ListenerBlock listenerBlock = new ListenerBlock();
+
+  public DebugTargetImpl(ILaunch launch, WorkspaceBridge.Factory workspaceBridgeFactory) {
     super(null);
+    this.workspaceBridgeFactory = workspaceBridgeFactory;
     this.launch = launch;
     this.threads = new JavascriptThread[] { new JavascriptThread(this) };
   }
@@ -80,28 +69,23 @@
    * Loads browser tabs, consults the {@code selector} which of the tabs to
    * attach to, and if any has been selected, requests an attachment to the tab.
    *
-   * @param projectNameBase to create for the browser scripts
    * @param remoteServer embedding application we are connected with
-   * @param attachCallback to invoke on successful attachment
+   * @param attachCallback to invoke on successful attachment, can fail to be called
    * @param monitor to report the progress to
    * @return whether the target has attached to a tab
    * @throws CoreException
    */
-  public boolean attach(String projectNameBase,
-      JavascriptVmEmbedder.ConnectionToRemote remoteServer, DestructingGuard destructingGuard,
-      Runnable attachCallback, IProgressMonitor monitor) throws CoreException {
+  public boolean attach(JavascriptVmEmbedder.ConnectionToRemote remoteServer,
+      DestructingGuard destructingGuard, Runnable attachCallback,
+      IProgressMonitor monitor) throws CoreException {
     monitor.beginTask("", 2); //$NON-NLS-1$
     JavascriptVmEmbedder.VmConnector connector = remoteServer.selectVm();
     if (connector == null) {
       return false;
     }
     monitor.worked(1);
-    return performAttach(projectNameBase, connector, destructingGuard, attachCallback);
-  }
-
-  private boolean performAttach(String projectNameBase, JavascriptVmEmbedder.VmConnector connector,
-      DestructingGuard destructingGuard, Runnable attachCallback) throws CoreException {
     final JavascriptVmEmbedder embedder = connector.attach(embedderListener, debugEventListener);
+    // From this moment V8 may call our listeners. We block them by listenerBlock for a while.
 
     Destructable embedderDestructor = new Destructable() {
       public void destruct() {
@@ -111,88 +95,44 @@
 
     destructingGuard.addValue(embedderDestructor);
 
-    vmEmbedder = embedder;
+    this.vmEmbedder = embedder;
 
-    // We might want to add some url-specific suffix here
-    String projectName = projectNameBase;
     // We'd like to know when launch is removed to remove our project.
     DebugPlugin.getDefault().getLaunchManager().addLaunchListener(launchListener);
-    this.debugProject = ChromiumDebugPluginUtil.createEmptyProject(projectName);
-    this.breakpointRegistry = new BreakpointRegistry();
-    this.resourceManager = new ResourceManager(debugProject, breakpointRegistry);
-    onAttach(projectName, attachCallback);
-    return true;
-  }
 
-  private void onAttach(String projectName, Runnable attachCallback) {
+    this.workspaceRelations = workspaceBridgeFactory.attachedToVm(this,
+        vmEmbedder.getJavascriptVm());
+    listenerBlock.unblock();
+
     DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
     reloadScriptsAndPossiblyResume(attachCallback);
+
+    return true;
   }
 
   private void reloadScriptsAndPossiblyResume(final Runnable attachCallback) {
-    reloadScripts(true, new Runnable() {
-      public void run() {
-        try {
-          if (attachCallback != null) {
-            attachCallback.run();
-          }
-        } finally {
-          fireCreationEvent();
-        }
-        Job job = new Job("Update debugger state") {
-          @Override
-          protected IStatus run(IProgressMonitor monitor) {
-            debugEventListener.resumedByDefault();
-            return Status.OK_STATUS;
-          }
-        };
-        job.schedule();
-      }
-    });
-  }
+    workspaceRelations.reloadScriptsAtStart();
 
-  private void reloadScripts(boolean isSync, final Runnable runnable) {
-    Runnable command = new Runnable() {
-      public void run() {
-        vmEmbedder.getJavascriptVm().getScripts(new ScriptsCallback() {
-          public void failure(String errorMessage) {
-            ChromiumDebugPlugin.logError(errorMessage);
-          }
+    try {
+      if (attachCallback != null) {
+        attachCallback.run();
+      }
+    } finally {
+      fireCreationEvent();
+    }
 
-          public void success(Collection<Script> scripts) {
-            if (!vmEmbedder.getJavascriptVm().isAttached()) {
-              return;
-            }
-            for (Script script : scripts) {
-              getResourceManager().addScript(script);
-            }
-            if (runnable != null) {
-              runnable.run();
-            }
-          }
-
-        });
+    Job job = new Job("Update debugger state") {
+      @Override
+      protected IStatus run(IProgressMonitor monitor) {
+        debugEventListener.resumedByDefault();
+        return Status.OK_STATUS;
       }
     };
-    if (isSync) {
-      command.run();
-      return;
-    }
-    Thread t = new Thread(command);
-    t.setDaemon(true);
-    t.start();
-    try {
-      t.join(OPERATION_TIMEOUT_MS);
-    } catch (InterruptedException e) {
-      ChromiumDebugPlugin.log(e);
-    }
+    job.schedule();
   }
 
   public String getName() throws DebugException {
-    if (vmEmbedder == null) {
-      return ""; //$NON-NLS-1$
-    }
-    return vmEmbedder.getTargetName();
+    return workspaceBridgeFactory.getLabelProvider().getTargetLabel(this);
   }
 
   public IProcess getProcess() {
@@ -214,8 +154,7 @@
   }
 
   public boolean supportsBreakpoint(IBreakpoint breakpoint) {
-    return ChromiumDebugPlugin.DEBUG_MODEL_ID.equals(breakpoint.getModelIdentifier()) &&
-        !isDisconnected();
+    return workspaceRelations.getBreakpointHandler().supportsBreakpoint(breakpoint);
   }
 
   @Override
@@ -228,9 +167,8 @@
     return launch;
   }
 
-  @Override
-  public String getModelIdentifier() {
-    return ChromiumDebugPlugin.DEBUG_MODEL_ID;
+  public String getChromiumModelIdentifier() {
+    return workspaceBridgeFactory.getDebugModelIdentifier();
   }
 
   public boolean canTerminate() {
@@ -270,6 +208,7 @@
   }
 
   public void resumed(int detail) {
+    debugContext = null;
     fireResumeEvent(detail);
   }
 
@@ -289,7 +228,7 @@
     if (!canDisconnect()) {
       return;
     }
-    removeAllBreakpoints();
+    workspaceRelations.beforeDetach();
     if (!vmEmbedder.getJavascriptVm().detach()) {
       ChromiumDebugPlugin.logWarning(Messages.DebugTargetImpl_BadResultWhileDisconnecting);
     }
@@ -312,10 +251,6 @@
     return false;
   }
 
-  public IProject getDebugProject() {
-    return debugProject;
-  }
-
   /**
    * Fires a debug event
    *
@@ -370,98 +305,34 @@
   }
 
   public void breakpointAdded(IBreakpoint breakpoint) {
-    if (!supportsBreakpoint(breakpoint)) {
-      return;
-    }
-    try {
-      if (breakpoint.isEnabled()) {
-        // Class cast is ensured by the supportsBreakpoint implementation
-        final ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
-        IFile file = (IFile) breakpoint.getMarker().getResource();
-        if (getResourceManager().isAddingFile(file)) {
-          return; // restoring breakpoints in progress
-        }
-        final Script script = getResourceManager().getScript(file);
-        if (script == null) {
-          // Might be a script from a different debug target
-          return;
-        }
-        final int line = (lineBreakpoint.getLineNumber() - 1) + script.getStartLine();
-        BreakpointCallback callback = new BreakpointCallback() {
-          public void success(Breakpoint breakpoint) {
-            lineBreakpoint.setBreakpoint(breakpoint);
-            breakpointRegistry.add(script, line, breakpoint);
-          }
-
-          public void failure(String errorMessage) {
-            ChromiumDebugPlugin.logError(errorMessage);
-          }
-        };
-        // ILineBreakpoint lines are 1-based while V8 lines are 0-based
-        JavascriptVm javascriptVm = vmEmbedder.getJavascriptVm();
-        if (script.getName() != null) {
-          javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_NAME,
-              script.getName(),
-              line,
-              Breakpoint.EMPTY_VALUE,
-              breakpoint.isEnabled(),
-              lineBreakpoint.getCondition(),
-              lineBreakpoint.getIgnoreCount(),
-              callback);
-        } else {
-          javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_ID,
-              String.valueOf(script.getId()),
-              line,
-              Breakpoint.EMPTY_VALUE,
-              breakpoint.isEnabled(),
-              lineBreakpoint.getCondition(),
-              lineBreakpoint.getIgnoreCount(),
-              callback);
-        }
-      }
-    } catch (CoreException e) {
-      ChromiumDebugPlugin.log(e);
-    }
+    workspaceRelations.getBreakpointHandler().breakpointAdded(breakpoint);
   }
 
   public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
-    if (!supportsBreakpoint(breakpoint)) {
-      return;
-    }
-    // Class cast is ensured by the supportsBreakpoint implementation
-    ((ChromiumLineBreakpoint) breakpoint).changed();
+    workspaceRelations.getBreakpointHandler().breakpointChanged(breakpoint, delta);
   }
 
   public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
-    if (!supportsBreakpoint(breakpoint)) {
-      return;
-    }
-    try {
-      if (breakpoint.isEnabled()) {
-        // Class cast is ensured by the supportsBreakpoint implementation
-        ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
-        lineBreakpoint.clear();
-        breakpointRegistry.remove(
-            getResourceManager().getScript((IFile) breakpoint.getMarker().getResource()),
-            lineBreakpoint.getLineNumber() - 1,
-            lineBreakpoint.getBrowserBreakpoint());
-      }
-    } catch (CoreException e) {
-      ChromiumDebugPlugin.log(e);
-    }
+    workspaceRelations.getBreakpointHandler().breakpointRemoved(breakpoint, delta);
   }
 
   @SuppressWarnings("unchecked")
   @Override
   public Object getAdapter(Class adapter) {
-    if (ILaunch.class.equals(adapter)) {
+    if (adapter == EvaluateContext.class) {
+      JavascriptThread thread = getThread();
+      if (thread == null) {
+        return null;
+      }
+      return thread.getAdapter(adapter);
+    } else if (adapter == ILaunch.class) {
       return this.launch;
     }
     return super.getAdapter(adapter);
   }
 
-  public IResourceManager getResourceManager() {
-    return resourceManager;
+  public IFile getScriptResource(Script script) {
+    return workspaceRelations.getScriptResource(script);
   }
 
   public JavascriptThread getThread() {
@@ -470,21 +341,6 @@
         : threads[0];
   }
 
-  private static void breakpointsHit(Collection<? extends Breakpoint> breakpointsHit) {
-    if (breakpointsHit.isEmpty()) {
-      return;
-    }
-    IBreakpoint[] breakpoints =
-        DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(
-            ChromiumDebugPlugin.DEBUG_MODEL_ID);
-    for (IBreakpoint breakpoint : breakpoints) {
-      ChromiumLineBreakpoint jsBreakpoint = (ChromiumLineBreakpoint) breakpoint;
-      if (breakpointsHit.contains(jsBreakpoint.getBrowserBreakpoint())) {
-        jsBreakpoint.setIgnoreCount(-1); // reset ignore count as we've hit it
-      }
-    }
-  }
-
   private static String trim(String text, int maxLength) {
     if (text == null || text.length() <= maxLength) {
       return text;
@@ -496,28 +352,6 @@
     return debugContext;
   }
 
-  public ISourceLocator getSourceLocator() {
-    return sourceLocator;
-  }
-
-  private void removeAllBreakpoints() {
-    IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
-    IBreakpoint[] breakpoints =
-        breakpointManager.getBreakpoints(ChromiumDebugPlugin.DEBUG_MODEL_ID);
-    for (IBreakpoint bp : breakpoints) {
-      ChromiumLineBreakpoint clb = (ChromiumLineBreakpoint) bp;
-      if (clb.getBrowserBreakpoint() != null &&
-          clb.getBrowserBreakpoint().getId() != Breakpoint.INVALID_ID) {
-        clb.getBrowserBreakpoint().clear(null);
-      }
-    }
-    try {
-      breakpointManager.removeBreakpoints(breakpoints, true);
-    } catch (CoreException e) {
-      ChromiumDebugPlugin.log(e);
-    }
-  }
-
   private final DebugEventListenerImpl debugEventListener = new DebugEventListenerImpl();
 
   class DebugEventListenerImpl implements DebugEventListener {
@@ -543,6 +377,7 @@
     }
 
     public void resumed() {
+      listenerBlock.waitUntilReady();
       synchronized (suspendResumeMonitor) {
         DebugTargetImpl.this.resumed(DebugEvent.CLIENT_REQUEST);
         alreadyResumedOrSuspended = true;
@@ -550,13 +385,15 @@
     }
 
     public void scriptLoaded(Script newScript) {
-      getResourceManager().addScript(newScript);
+      listenerBlock.waitUntilReady();
+      workspaceRelations.scriptLoaded(newScript);
     }
 
     public void suspended(DebugContext context) {
+      listenerBlock.waitUntilReady();
       synchronized (suspendResumeMonitor) {
         DebugTargetImpl.this.debugContext = context;
-        breakpointsHit(context.getBreakpointsHit());
+        workspaceRelations.getBreakpointHandler().breakpointsHit(context.getBreakpointsHit());
         int suspendedDetail;
         if (context.getState() == State.EXCEPTION) {
           logExceptionFromContext(context);
@@ -593,7 +430,8 @@
   private final JavascriptVmEmbedder.Listener embedderListener =
       new JavascriptVmEmbedder.Listener() {
     public void reset() {
-      getResourceManager().clear();
+      listenerBlock.waitUntilReady();
+      workspaceRelations.handleVmResetEvent();
       fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.STATE));
     }
     public void closed() {
@@ -612,9 +450,7 @@
         return;
       }
       DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
-      if (debugProject != null) {
-        ChromiumDebugPluginUtil.deleteVirtualProjectAsync(debugProject);
-      }
+      workspaceRelations.launchRemoved();
     }
   };
 
@@ -635,23 +471,32 @@
     }
   };
 
-  /**
-   * This very simple source locator works because we provide our own source files.
-   * We'll have to try harder, once we link with resource js files.
-   */
-  private final ISourceLocator sourceLocator = new ISourceLocator() {
-    public Object getSourceElement(IStackFrame stackFrame) {
-      if (stackFrame instanceof StackFrame == false) {
-        return null;
+  public WorkspaceBridge.JsLabelProvider getLabelProvider() {
+    return workspaceBridgeFactory.getLabelProvider();
+  }
+
+  private static class ListenerBlock {
+    private volatile boolean isBlocked = true;
+    private final Object monitor = new Object();
+    void waitUntilReady() {
+      if (isBlocked) {
+        return;
       }
-      StackFrame jsStackFrame = (StackFrame) stackFrame;
-
-      Script script = jsStackFrame.getCallFrame().getScript();
-      if (script == null) {
-        return null;
+      synchronized (monitor) {
+        while (isBlocked) {
+          try {
+            monitor.wait();
+          } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+          }
+        }
       }
-
-      return resourceManager.getResource(script);
     }
-  };
+    void unblock() {
+      isBlocked = true;
+      synchronized (monitor) {
+        monitor.notifyAll();
+      }
+    }
+  }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/EvaluateContext.java	Wed Jan 27 15:59:22 2010 -0800
@@ -0,0 +1,28 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.debug.core.model;
+
+import org.chromium.sdk.JsEvaluateContext;
+
+/**
+ * Projection of {@link JsEvaluateContext} into Eclipse world.
+ */
+public class EvaluateContext {
+  private final JsEvaluateContext jsEvaluateContext;
+  private final DebugTargetImpl debugTargetImpl;
+
+  EvaluateContext(JsEvaluateContext jsEvaluateContext, DebugTargetImpl debugTargetImpl) {
+    this.jsEvaluateContext = jsEvaluateContext;
+    this.debugTargetImpl = debugTargetImpl;
+  }
+
+  public JsEvaluateContext getJsEvaluateContext() {
+    return jsEvaluateContext;
+  }
+
+  public DebugTargetImpl getDebugTarget() {
+    return debugTargetImpl;
+  }
+}
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/IChromiumDebugTarget.java	Wed Jan 27 15:47:03 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-package org.chromium.debug.core.model;
-
-import org.chromium.sdk.DebugContext;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.debug.core.model.IDebugTarget;
-
-public interface IChromiumDebugTarget extends IDebugTarget {
-	DebugContext getDebugContext();
-	void fireResumeEvent(int detail);
-	JavascriptVmEmbedder getJavascriptEmbedder();
-	IResourceManager getResourceManager();
-	IProject getDebugProject();
-}
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/IResourceManager.java	Wed Jan 27 15:47:03 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-package org.chromium.debug.core.model;
-
-import org.chromium.sdk.Script;
-import org.eclipse.core.resources.IFile;
-
-public interface IResourceManager {
-	IFile getResource(Script script);
-	void addScript(Script script);
-	boolean isAddingFile(IFile file);
-	Script getScript(IFile file);
-	void clear();
-}
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/JavascriptThread.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/JavascriptThread.java	Wed Jan 27 15:59:22 2010 -0800
@@ -8,14 +8,16 @@
 
 import org.chromium.debug.core.ChromiumDebugPlugin;
 import org.chromium.sdk.CallFrame;
+import org.chromium.sdk.DebugContext;
 import org.chromium.sdk.DebugContext.StepAction;
 import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.debug.core.DebugEvent;
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.debug.core.model.IBreakpoint;
 import org.eclipse.debug.core.model.IStackFrame;
 import org.eclipse.debug.core.model.IThread;
-import org.eclipse.osgi.util.NLS;
 
 /**
  * This class represents the only Chromium V8 VM thread.
@@ -46,25 +48,25 @@
    *
    * @param debugTarget this thread is created for
    */
-  public JavascriptThread(IChromiumDebugTarget debugTarget) {
+  public JavascriptThread(DebugTargetImpl debugTarget) {
     super(debugTarget);
   }
 
   public StackFrame[] getStackFrames() throws DebugException {
-    if (isSuspended()) {
-      ensureStackFrames();
-      return stackFrames;
-    } else {
-      return EMPTY_FRAMES;
-    }
+    ensureStackFrames(getDebugTarget().getDebugContext());
+    return stackFrames;
   }
 
   public void reset() {
     this.stackFrames = null;
   }
 
-  private void ensureStackFrames() {
-    this.stackFrames = wrapStackFrames(getDebugTarget().getDebugContext().getCallFrames());
+  private void ensureStackFrames(DebugContext debugContext) {
+    if (debugContext == null) {
+      this.stackFrames = EMPTY_FRAMES;
+    } else {
+      this.stackFrames = wrapStackFrames(debugContext.getCallFrames());
+    }
   }
 
   private StackFrame[] wrapStackFrames(List<? extends CallFrame> jsFrames) {
@@ -92,11 +94,7 @@
   }
 
   public String getName() throws DebugException {
-    String url = getDebugTarget().getJavascriptEmbedder().getThreadName();
-    return NLS.bind(Messages.JsThread_ThreadLabelFormat, (isSuspended()
-        ? Messages.JsThread_ThreadLabelSuspended
-        : Messages.JsThread_ThreadLabelRunning), (url.length() > 0
-        ? (" : " + url) : "")); //$NON-NLS-1$ //$NON-NLS-2$
+    return getDebugTarget().getLabelProvider().getThreadLabel(this);
   }
 
   public IBreakpoint[] getBreakpoints() {
@@ -148,8 +146,13 @@
   }
 
   private void step(StepAction stepAction, int detail) throws DebugException {
+    DebugContext debugContext = getDebugTarget().getDebugContext();
+    if (debugContext == null) {
+      throw new DebugException(new Status(IStatus.ERROR, ChromiumDebugPlugin.PLUGIN_ID,
+          "Step attempted while not suspended")); //$NON-NLS-1$
+    }
     setStepping(true);
-    getDebugTarget().getDebugContext().continueVm(stepAction, 1, null);
+    debugContext.continueVm(stepAction, 1, null);
     // The suspend event should be fired once the backtrace is ready
     // (in BacktraceProcessor).
     getDebugTarget().fireResumeEvent(detail);
@@ -189,12 +192,12 @@
   @Override
   @SuppressWarnings("unchecked")
   public Object getAdapter(Class adapter) {
-    if (adapter == StackFrame.class) {
-      try {
-        return getTopStackFrame();
-      } catch (DebugException e) {
-        ChromiumDebugPlugin.log(e);
+    if (adapter == EvaluateContext.class) {
+      DebugContext debugContext = getDebugTarget().getDebugContext();
+      if (debugContext == null) {
+        return null;
       }
+      return new EvaluateContext(debugContext.getGlobalEvaluateContext(), getDebugTarget());
     }
     return super.getAdapter(adapter);
   }
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/LineBreakpointAdapter.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/LineBreakpointAdapter.java	Wed Jan 27 15:59:22 2010 -0800
@@ -4,7 +4,6 @@
 
 package org.chromium.debug.core.model;
 
-import org.chromium.debug.core.ChromiumDebugPlugin;
 import org.chromium.debug.core.util.ChromiumDebugPluginUtil;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
@@ -20,7 +19,27 @@
 /**
  * Adapter to create breakpoints in JS files.
  */
-public class LineBreakpointAdapter implements IToggleBreakpointsTarget {
+public abstract class LineBreakpointAdapter implements IToggleBreakpointsTarget {
+
+  public static class ForVirtualProject extends LineBreakpointAdapter {
+    @Override
+    protected ITextEditor getEditor(IWorkbenchPart part) {
+      if (part instanceof ITextEditor) {
+        ITextEditor editorPart = (ITextEditor) part;
+        IResource resource = (IResource) editorPart.getEditorInput().getAdapter(IResource.class);
+        if (resource != null &&
+            ChromiumDebugPluginUtil.CHROMIUM_EXTENSION.equals(resource.getFileExtension())) {
+          return editorPart;
+        }
+      }
+      return null;
+    }
+
+    @Override
+    protected String getDebugModelId() {
+      return VProjectWorkspaceBridge.DEBUG_MODEL_ID;
+    }
+  }
 
   public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection)
       throws CoreException {
@@ -30,7 +49,7 @@
       ITextSelection textSelection = (ITextSelection) selection;
       int lineNumber = textSelection.getStartLine();
       IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(
-          ChromiumDebugPlugin.DEBUG_MODEL_ID);
+          getDebugModelId());
       for (int i = 0; i < breakpoints.length; i++) {
         IBreakpoint breakpoint = breakpoints[i];
         if (resource.equals(breakpoint.getMarker().getResource())) {
@@ -59,17 +78,9 @@
    * @return the editor being used to edit a PDA file, associated with the given
    *         part, or <code>null</code> if none
    */
-  protected ITextEditor getEditor(IWorkbenchPart part) {
-    if (part instanceof ITextEditor) {
-      ITextEditor editorPart = (ITextEditor) part;
-      IResource resource = (IResource) editorPart.getEditorInput().getAdapter(IResource.class);
-      if (resource != null &&
-          ChromiumDebugPluginUtil.CHROMIUM_EXTENSION.equals(resource.getFileExtension())) {
-        return editorPart;
-      }
-    }
-    return null;
-  }
+  protected abstract ITextEditor getEditor(IWorkbenchPart part);
+
+  protected abstract String getDebugModelId();
 
   public void toggleMethodBreakpoints(IWorkbenchPart part, ISelection selection)
       throws CoreException {
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/Messages.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/Messages.java	Wed Jan 27 15:59:22 2010 -0800
@@ -21,6 +21,8 @@
 
   public static String ChromiumTabSelectionDialog_UrlColumnName;
 
+  public static String ConnectionLoggerImpl_MessageSeparator;
+
   public static String ConnectionLoggerImpl_ReceivedFromChrome;
 
   public static String ConnectionLoggerImpl_SentToChrome;
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/ResourceManager.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/ResourceManager.java	Wed Jan 27 15:59:22 2010 -0800
@@ -24,7 +24,7 @@
  * This object handles the mapping between {@link Script}s and their corresponding resources
  * inside Eclipse.
  */
-public class ResourceManager implements IResourceManager {
+public class ResourceManager {
   private final Map<IFile, Script> resourceToScript = new HashMap<IFile, Script>();
   private final Map<ScriptIdentifier, IFile> scriptIdToResource =
       new HashMap<ScriptIdentifier, IFile>();
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/StackFrame.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/StackFrame.java	Wed Jan 27 15:59:22 2010 -0800
@@ -7,10 +7,12 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 import org.chromium.debug.core.ChromiumDebugPlugin;
 import org.chromium.sdk.CallFrame;
+import org.chromium.sdk.DebugContext;
 import org.chromium.sdk.JsArray;
 import org.chromium.sdk.JsFunction;
 import org.chromium.sdk.JsObject;
@@ -26,7 +28,6 @@
 import org.eclipse.debug.core.model.IStackFrame;
 import org.eclipse.debug.core.model.IThread;
 import org.eclipse.debug.core.model.IVariable;
-import org.eclipse.osgi.util.NLS;
 
 /**
  * An IStackFrame implementation over a JsStackFrame instance.
@@ -47,7 +48,7 @@
    * @param thread for which the stack frame is created
    * @param stackFrame an underlying SDK stack frame
    */
-  public StackFrame(IChromiumDebugTarget debugTarget, JavascriptThread thread, CallFrame stackFrame) {
+  public StackFrame(DebugTargetImpl debugTarget, JavascriptThread thread, CallFrame stackFrame) {
     super(debugTarget);
     this.thread = thread;
     this.stackFrame = stackFrame;
@@ -77,19 +78,22 @@
   }
 
   static IVariable[] wrapVariables(
-      IChromiumDebugTarget debugTarget, Collection<? extends JsVariable> jsVars,
+      DebugTargetImpl debugTarget, Collection<? extends JsVariable> jsVars,
       Collection <? extends JsVariable> jsInternalProperties) {
     List<Variable> vars = new ArrayList<Variable>(jsVars.size());
     for (JsVariable jsVar : jsVars) {
       vars.add(new Variable(debugTarget, jsVar, false));
     }
+    // Sort all regular properties by name.
+    Collections.sort(vars, VARIABLE_COMPARATOR);
+    // Always put internal properties in the end.
     for (JsVariable jsMetaVar : jsInternalProperties) {
       vars.add(new Variable(debugTarget, jsMetaVar, true));
     }
     return vars.toArray(new IVariable[vars.size()]);
   }
 
-  static IVariable[] wrapScopes(IChromiumDebugTarget debugTarget, List<? extends JsScope> jsScopes,
+  static IVariable[] wrapScopes(DebugTargetImpl debugTarget, List<? extends JsScope> jsScopes,
       JsVariable receiverVariable) {
     List<Variable> vars = new ArrayList<Variable>();
 
@@ -101,9 +105,13 @@
         }
         vars.add(new Variable(debugTarget, wrapScopeAsVariable(scope), false));
       } else {
+        int startPos = vars.size();
         for (JsVariable var : scope.getVariables()) {
           vars.add(new Variable(debugTarget, var, false));
         }
+        int endPos = vars.size();
+        List<Variable> sublist = vars.subList(startPos, endPos);
+        Collections.sort(sublist, VARIABLE_COMPARATOR);
       }
     }
     if (receiverVariable != null) {
@@ -199,16 +207,7 @@
   }
 
   public String getName() throws DebugException {
-    String name = stackFrame.getFunctionName();
-    Script script = stackFrame.getScript();
-    if (script == null) {
-      return Messages.StackFrame_UnknownScriptName;
-    }
-    int line = script.getStartLine() + getLineNumber();
-    if (line != -1) {
-      name = NLS.bind(Messages.StackFrame_NameFormat, new Object[] {name, script.getName(), line});
-    }
-    return name;
+    return getDebugTarget().getLabelProvider().getStackFrameLabel(this);
   }
 
   public IRegisterGroup[] getRegisterGroups() throws DebugException {
@@ -306,4 +305,22 @@
     return stackFrame.hashCode();
   }
 
+  private final static Comparator<Variable> VARIABLE_COMPARATOR = new Comparator<Variable>() {
+    public int compare(Variable var1, Variable var2) {
+      return var1.getName().compareTo(var2.getName());
+    }
+  };
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public Object getAdapter(Class adapter) {
+    if (adapter == EvaluateContext.class) {
+      DebugContext debugContext = getDebugTarget().getDebugContext();
+      if (debugContext == null) {
+        return null;
+      }
+      return new EvaluateContext(getCallFrame().getEvaluateContext(), getDebugTarget());
+    }
+    return super.getAdapter(adapter);
+  }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/VProjectWorkspaceBridge.java	Wed Jan 27 15:59:22 2010 -0800
@@ -0,0 +1,285 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.debug.core.model;
+
+import java.util.Collection;
+
+import org.chromium.debug.core.ChromiumDebugPlugin;
+import org.chromium.debug.core.util.ChromiumDebugPluginUtil;
+import org.chromium.sdk.Breakpoint;
+import org.chromium.sdk.CallFrame;
+import org.chromium.sdk.JavascriptVm;
+import org.chromium.sdk.Script;
+import org.chromium.sdk.JavascriptVm.BreakpointCallback;
+import org.chromium.sdk.JavascriptVm.ScriptsCallback;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IBreakpointManager;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.ISourceLocator;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Virtual project-supporting implementation of {@link WorkspaceBridge}.
+ */
+public class VProjectWorkspaceBridge implements WorkspaceBridge {
+  /** The debug model ID. */
+  public static final String DEBUG_MODEL_ID = "org.chromium.debug"; //$NON-NLS-1$
+
+  public static class FactoryImpl implements Factory {
+    private final String projectNameBase;
+
+    public FactoryImpl(String projectNameBase) {
+      this.projectNameBase = projectNameBase;
+    }
+
+    public WorkspaceBridge attachedToVm(DebugTargetImpl debugTargetImpl,
+        JavascriptVm javascriptVm) {
+      // We might want to add URL or something to project name.
+      return new VProjectWorkspaceBridge(projectNameBase, debugTargetImpl, javascriptVm);
+    }
+
+    public String getDebugModelIdentifier() {
+      return DEBUG_MODEL_ID;
+    }
+
+    public JsLabelProvider getLabelProvider() {
+      return LABEL_PROVIDER;
+    }
+  }
+
+  private final IProject debugProject;
+  private final JavascriptVm javascriptVm;
+  private final ResourceManager resourceManager;
+  private final BreakpointRegistry breakpointRegistry = new BreakpointRegistry();
+  private final DebugTargetImpl debugTargetImpl;
+
+  public VProjectWorkspaceBridge(String projectName, DebugTargetImpl debugTargetImpl,
+      JavascriptVm javascriptVm) {
+    this.debugTargetImpl = debugTargetImpl;
+    this.javascriptVm = javascriptVm;
+    this.debugProject = ChromiumDebugPluginUtil.createEmptyProject(projectName);
+    this.resourceManager = new ResourceManager(debugProject, breakpointRegistry);
+    ILaunch launch = debugTargetImpl.getLaunch();
+    launch.setSourceLocator(sourceLocator);
+  }
+
+  public void launchRemoved() {
+    if (debugProject != null) {
+      ChromiumDebugPluginUtil.deleteVirtualProjectAsync(debugProject);
+    }
+  }
+
+  public void beforeDetach() {
+    IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
+    IBreakpoint[] breakpoints =
+        breakpointManager.getBreakpoints(DEBUG_MODEL_ID);
+    for (IBreakpoint bp : breakpoints) {
+      ChromiumLineBreakpoint clb = (ChromiumLineBreakpoint) bp;
+      if (clb.getBrowserBreakpoint() != null &&
+          clb.getBrowserBreakpoint().getId() != Breakpoint.INVALID_ID) {
+        clb.getBrowserBreakpoint().clear(null);
+      }
+    }
+    try {
+      breakpointManager.removeBreakpoints(breakpoints, true);
+    } catch (CoreException e) {
+      ChromiumDebugPlugin.log(e);
+    }
+  }
+
+  public void handleVmResetEvent() {
+    resourceManager.clear();
+  }
+
+  public void scriptLoaded(Script newScript) {
+    resourceManager.addScript(newScript);
+  }
+
+  public void reloadScriptsAtStart() {
+    javascriptVm.getScripts(new ScriptsCallback() {
+      public void failure(String errorMessage) {
+        ChromiumDebugPlugin.logError(errorMessage);
+      }
+
+      public void success(Collection<Script> scripts) {
+        if (!javascriptVm.isAttached()) {
+          return;
+        }
+        for (Script script : scripts) {
+          resourceManager.addScript(script);
+        }
+      }
+    });
+  }
+
+  public IFile getScriptResource(Script script) {
+    return resourceManager.getResource(script);
+  }
+
+  public BreakpointHandler getBreakpointHandler() {
+    return breakpointHandler;
+  }
+
+  private final BreakpointHandler breakpointHandler = new BreakpointHandler() {
+    public boolean supportsBreakpoint(IBreakpoint breakpoint) {
+      return DEBUG_MODEL_ID.equals(breakpoint.getModelIdentifier()) &&
+          !debugTargetImpl.isDisconnected();
+    }
+    public void breakpointAdded(IBreakpoint breakpoint) {
+      if (!supportsBreakpoint(breakpoint)) {
+        return;
+      }
+      try {
+        if (breakpoint.isEnabled()) {
+          // Class cast is ensured by the supportsBreakpoint implementation
+          final ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
+          IFile file = (IFile) breakpoint.getMarker().getResource();
+          if (resourceManager.isAddingFile(file)) {
+            return; // restoring breakpoints in progress
+          }
+          final Script script = resourceManager.getScript(file);
+          if (script == null) {
+            // Might be a script from a different debug target
+            return;
+          }
+          // ILineBreakpoint lines are 1-based while V8 lines are 0-based
+          final int line = (lineBreakpoint.getLineNumber() - 1) + script.getStartLine();
+          BreakpointCallback callback = new BreakpointCallback() {
+            public void success(Breakpoint breakpoint) {
+              lineBreakpoint.setBreakpoint(breakpoint);
+              breakpointRegistry.add(script, line, breakpoint);
+            }
+
+            public void failure(String errorMessage) {
+              ChromiumDebugPlugin.logError(errorMessage);
+            }
+          };
+          if (script.getName() != null) {
+            javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_NAME,
+                script.getName(),
+                line,
+                Breakpoint.EMPTY_VALUE,
+                breakpoint.isEnabled(),
+                lineBreakpoint.getCondition(),
+                lineBreakpoint.getIgnoreCount(),
+                callback);
+          } else {
+            javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_ID,
+                String.valueOf(script.getId()),
+                line,
+                Breakpoint.EMPTY_VALUE,
+                breakpoint.isEnabled(),
+                lineBreakpoint.getCondition(),
+                lineBreakpoint.getIgnoreCount(),
+                callback);
+          }
+        }
+      } catch (CoreException e) {
+        ChromiumDebugPlugin.log(e);
+      }
+    }
+
+    public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
+      if (!supportsBreakpoint(breakpoint)) {
+        return;
+      }
+      // Class cast is ensured by the supportsBreakpoint implementation
+      ((ChromiumLineBreakpoint) breakpoint).changed();
+    }
+
+    public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
+      if (!supportsBreakpoint(breakpoint)) {
+        return;
+      }
+      try {
+        if (breakpoint.isEnabled()) {
+          // Class cast is ensured by the supportsBreakpoint implementation
+          ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
+          lineBreakpoint.clear();
+          breakpointRegistry.remove(
+              resourceManager.getScript((IFile) breakpoint.getMarker().getResource()),
+              lineBreakpoint.getLineNumber() - 1,
+              lineBreakpoint.getBrowserBreakpoint());
+        }
+      } catch (CoreException e) {
+        ChromiumDebugPlugin.log(e);
+      }
+    }
+
+    public void breakpointsHit(Collection<? extends Breakpoint> breakpointsHit) {
+      if (breakpointsHit.isEmpty()) {
+        return;
+      }
+      IBreakpoint[] breakpoints =
+          DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DEBUG_MODEL_ID);
+      for (IBreakpoint breakpoint : breakpoints) {
+        ChromiumLineBreakpoint jsBreakpoint = (ChromiumLineBreakpoint) breakpoint;
+        if (breakpointsHit.contains(jsBreakpoint.getBrowserBreakpoint())) {
+          jsBreakpoint.setIgnoreCount(-1); // reset ignore count as we've hit it
+        }
+      }
+    }
+  };
+
+  /**
+   * This very simple source locator works because we provide our own source files.
+   * We'll have to try harder, once we link with resource js files.
+   */
+  private final ISourceLocator sourceLocator = new ISourceLocator() {
+    public Object getSourceElement(IStackFrame stackFrame) {
+      if (stackFrame instanceof StackFrame == false) {
+        return null;
+      }
+      StackFrame jsStackFrame = (StackFrame) stackFrame;
+
+      Script script = jsStackFrame.getCallFrame().getScript();
+      if (script == null) {
+        return null;
+      }
+
+      return resourceManager.getResource(script);
+    }
+  };
+
+  private final static JsLabelProvider LABEL_PROVIDER = new JsLabelProvider() {
+    public String getTargetLabel(DebugTargetImpl debugTarget) {
+      JavascriptVmEmbedder vmEmbedder = debugTarget.getJavascriptEmbedder();
+      if (vmEmbedder == null) {
+        return ""; //$NON-NLS-1$
+      }
+      return vmEmbedder.getTargetName();
+    }
+
+    public String getThreadLabel(JavascriptThread thread) {
+      String url = thread.getDebugTarget().getJavascriptEmbedder().getThreadName();
+      return NLS.bind(Messages.JsThread_ThreadLabelFormat, (thread.isSuspended()
+          ? Messages.JsThread_ThreadLabelSuspended
+          : Messages.JsThread_ThreadLabelRunning), (url.length() > 0
+          ? (" : " + url) : "")); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    public String getStackFrameLabel(StackFrame stackFrame) throws DebugException {
+      CallFrame callFrame = stackFrame.getCallFrame();
+      String name = callFrame.getFunctionName();
+      Script script = callFrame.getScript();
+      if (script == null) {
+        return Messages.StackFrame_UnknownScriptName;
+      }
+      int line = script.getStartLine() + stackFrame.getLineNumber();
+      if (line != -1) {
+        name = NLS.bind(Messages.StackFrame_NameFormat,
+            new Object[] {name, script.getName(), line});
+      }
+      return name;
+    }
+  };
+}
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/Value.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/Value.java	Wed Jan 27 15:59:22 2010 -0800
@@ -25,14 +25,14 @@
 
   private IVariable[] variables;
 
-  public static Value create(IChromiumDebugTarget debugTarget, JsValue value) {
+  public static Value create(DebugTargetImpl debugTarget, JsValue value) {
     if (JsValue.Type.TYPE_ARRAY == value.getType()) {
       return new ArrayValue(debugTarget, (JsArray) value);
     }
     return new Value(debugTarget, value);
   }
 
-  Value(IChromiumDebugTarget debugTarget, JsValue value) {
+  Value(DebugTargetImpl debugTarget, JsValue value) {
     super(debugTarget);
     this.value = value;
   }
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/Variable.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/Variable.java	Wed Jan 27 15:59:22 2010 -0800
@@ -26,13 +26,13 @@
    */
   private final boolean isInternalProperty;
 
-  public Variable(IChromiumDebugTarget debugTarget, JsVariable variable, boolean isInternalProperty) {
+  public Variable(DebugTargetImpl debugTarget, JsVariable variable, boolean isInternalProperty) {
     super(debugTarget);
     this.variable = variable;
     this.isInternalProperty = isInternalProperty;
   }
 
-  public String getName() throws DebugException {
+  public String getName() {
     return variable.getName();
   }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/WorkspaceBridge.java	Wed Jan 27 15:59:22 2010 -0800
@@ -0,0 +1,115 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.debug.core.model;
+
+import java.util.Collection;
+
+import org.chromium.sdk.Breakpoint;
+import org.chromium.sdk.JavascriptVm;
+import org.chromium.sdk.Script;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.IBreakpointListener;
+import org.eclipse.debug.core.model.IBreakpoint;
+
+
+/**
+ * This interface draws a connection between V8 debug target and Eclipse workspace with its
+ * resources. Instance of this interface corresponds to a particular target. It is oriented
+ * to "virtual project" model, when all source files are virtual and downloaded right from
+ * running V8. "Native" model, when all source files are regular files of Eclipse workspace
+ * (and are only supposed to correspond to scripts that are actually running in remote V8)
+ * is also supported and assumes stub implementations for most of methods.
+ */
+public interface WorkspaceBridge {
+
+  /**
+   * A factory interface for {@link WorkspaceBridge}. It seems to tend to become
+   * a workspace relations type object, that is not tied to a particular {@link DebugTargetImpl},
+   * but so far it only has 1 additional method.
+   */
+  interface Factory {
+    /**
+     * Creates new instance of {@link WorkspaceBridge} when connection to V8 VM is already
+     * established.
+     */
+    WorkspaceBridge attachedToVm(DebugTargetImpl debugTargetImpl, JavascriptVm javascriptVm);
+
+    String getDebugModelIdentifier();
+
+    /**
+     * Since we define here how scripts are mapped to workspace, we may want to specify
+     * labels in UI. Each type of bridges provides its own label providers here.
+     * User may cache value of this method.
+     */
+    JsLabelProvider getLabelProvider();
+  }
+
+  /**
+   * Helps UI actions to map from script to resource.
+   */
+  IFile getScriptResource(Script script);
+
+  /**
+   * Called at starting period of time, requires all scripts to be (re)loaded.
+   */
+  void reloadScriptsAtStart();
+
+  /**
+   * Reports about new script loaded in JavaScript VM.
+   */
+  void scriptLoaded(Script newScript);
+
+  /**
+   * Handles reset event in JavaScript VM (e.g. Chromium tab reload or navigate event).
+   * The whole context changes.
+   */
+  void handleVmResetEvent();
+
+  /**
+   * Detach command is about to be sent to JavaScript VM.
+   */
+  void beforeDetach();
+
+  /**
+   * Virtual project is expected to stay live until launch is removed from Launches view. Then
+   * it has to go.
+   */
+  void launchRemoved();
+
+  /**
+   * Returns instance of breakpoint handler. Should be a simple getter, caller may cache result
+   * value.
+   */
+  BreakpointHandler getBreakpointHandler();
+
+  /**
+   * Breakpoint-related aspect of {@link WorkspaceBridge} interface.
+   */
+  interface BreakpointHandler extends IBreakpointListener {
+    boolean supportsBreakpoint(IBreakpoint breakpoint);
+    void breakpointsHit(Collection<? extends Breakpoint> breakpointsHit);
+  }
+
+  /**
+   * Label provider for several debug elements. This object should be stateless.
+   */
+  interface JsLabelProvider {
+    /**
+     * Label for the debug target to be shown in the Debug view.
+     */
+    String getTargetLabel(DebugTargetImpl debugTarget) throws DebugException;
+
+    /**
+     * Label for JavaScript thread to be shown in the Debug view.
+     */
+    String getThreadLabel(JavascriptThread thread) throws DebugException;
+
+    /**
+     * Label for stack frame to be shown in the Debug view.
+     */
+    String getStackFrameLabel(StackFrame stackFrame) throws DebugException;
+  }
+}
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/messages.properties	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/messages.properties	Wed Jan 27 15:59:22 2010 -0800
@@ -6,6 +6,7 @@
 ChromiumTabSelectionDialog_IdColumnName=ID
 ChromiumTabSelectionDialog_TableTitle=Available Tabs
 ChromiumTabSelectionDialog_UrlColumnName=Tab URL
+ConnectionLoggerImpl_MessageSeparator=\n> end of message\n
 ConnectionLoggerImpl_ReceivedFromChrome=Received from Chrome:
 ConnectionLoggerImpl_SentToChrome=Sent to Chrome:
 DebugTargetImpl_BadResultWhileDisconnecting=Received bad result from browser while disconnecting
--- a/org.chromium.debug.ui/META-INF/MANIFEST.MF	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.ui/META-INF/MANIFEST.MF	Wed Jan 27 15:59:22 2010 -0800
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.chromium.debug.ui;singleton:=true
-Bundle-Version: 0.1.3.qualifier
+Bundle-Version: 0.1.5.qualifier
 Bundle-Activator: org.chromium.debug.ui.ChromiumDebugUIPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
@@ -13,7 +13,7 @@
  org.eclipse.jface.text;bundle-version="3.4.1",
  org.eclipse.core.variables;bundle-version="3.2.100",
  org.eclipse.ui.ide;bundle-version="3.4.1",
- org.chromium.debug.core;bundle-version="0.1.3",
- org.chromium.sdk;bundle-version="0.1.3"
+ org.chromium.debug.core;bundle-version="0.1.5",
+ org.chromium.sdk;bundle-version="0.1.5"
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
--- a/org.chromium.debug.ui/src/org/chromium/debug/ui/JsDebugModelPresentation.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/JsDebugModelPresentation.java	Wed Jan 27 15:59:22 2010 -0800
@@ -69,25 +69,27 @@
   }
 
   public String getEditorId(IEditorInput input, Object element) {
-	IFile file = null;
-	if (element instanceof IFile) {
-	  file = (IFile) element;
-	} else if (element instanceof IBreakpoint) {
-	  // Ñan the breakpoint marker be on the folder/project? Everything is possible with plugins...
-	  IResource resource = ((IBreakpoint) element).getMarker().getResource();
-	  if (resource instanceof IFile) {
-	    file = (IFile) resource;
-	  }
-	}
-	if (file != null) {
-	  // Notice that this method will pick the editor not only on extension mapping basis but also user preference 
-	  try {
-	    return IDE.getEditorDescriptor(file).getId();
-	  } catch (PartInitException e) {
-	    return JsEditor.EDITOR_ID;
-	  }
-	}
+    IFile file;
+    if (element instanceof IFile) {
+      file = (IFile) element;
+    } else if (element instanceof IBreakpoint) {
+        IBreakpoint breakpoint = (IBreakpoint) element;
+        IResource resource = breakpoint.getMarker().getResource();
+        // Can the breakpoint resource be folder or project? Better check for it.
+      if (resource instanceof IFile == false) {
+        return null;
+      }
+      file = (IFile) resource;
+    } else {
+      return null;
+    }
 
-    return null;
+    // Pick the editor based on the file extension, taking user preferences into account.
+    try {
+      return IDE.getEditorDescriptor(file).getId();
+    } catch (PartInitException e) {
+      // TODO(peter.rybin): should it really be the default case? There might be no virtual project.
+      return JsEditor.EDITOR_ID;
+    }
   }
 }
--- a/org.chromium.debug.ui/src/org/chromium/debug/ui/JsEvalContextManager.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/JsEvalContextManager.java	Wed Jan 27 15:59:22 2010 -0800
@@ -9,7 +9,7 @@
 import java.util.Map;
 import java.util.Set;
 
-import org.chromium.debug.core.model.StackFrame;
+import org.chromium.debug.core.model.EvaluateContext;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.debug.ui.DebugUITools;
 import org.eclipse.debug.ui.contexts.DebugContextEvent;
@@ -35,8 +35,8 @@
 
   private IWorkbenchWindow activeWindow;
 
-  private final Map<IWorkbenchPage, StackFrame> pageToFrame =
-      new HashMap<IWorkbenchPage, StackFrame>();
+  private final Map<IWorkbenchPage, EvaluateContext> pageToFrame =
+      new HashMap<IWorkbenchPage, EvaluateContext>();
 
   protected JsEvalContextManager() {
     DebugUITools.getDebugContextManager().addDebugContextListener(this);
@@ -83,7 +83,9 @@
       if (selection instanceof IStructuredSelection) {
         Object firstElement = ((IStructuredSelection) selection).getFirstElement();
         if (firstElement instanceof IAdaptable) {
-          StackFrame frame = (StackFrame) ((IAdaptable) firstElement).getAdapter(StackFrame.class);
+          IAdaptable adaptable = (IAdaptable) firstElement;
+
+          EvaluateContext frame = (EvaluateContext) adaptable.getAdapter(EvaluateContext.class);
           if (frame != null) {
             putStackFrame(page, frame);
             return;
@@ -103,9 +105,9 @@
    * @return the stack frame in whose context the evaluation is performed, or
    *         {@code null} if none
    */
-  public static StackFrame getStackFrameFor(IWorkbenchPart part) {
+  public static EvaluateContext getStackFrameFor(IWorkbenchPart part) {
     IWorkbenchPage page = part.getSite().getPage();
-    StackFrame frame = getStackFrameFor(page);
+    EvaluateContext frame = getStackFrameFor(page);
     if (frame == null) {
       return getStackFrameFor(page.getWorkbenchWindow());
     }
@@ -121,7 +123,7 @@
    * @return the stack frame in whose the evaluation is performed, or {@code
    *         null} if none
    */
-  public static StackFrame getStackFrameFor(IWorkbenchWindow window) {
+  public static EvaluateContext getStackFrameFor(IWorkbenchWindow window) {
     Set<IWorkbenchWindow> visitedWindows = new HashSet<IWorkbenchWindow>();
     if (window == null) {
       window = instance.activeWindow;
@@ -129,10 +131,10 @@
     return getStackFrameFor(window, visitedWindows);
   }
 
-  private static StackFrame getStackFrameFor(
+  private static EvaluateContext getStackFrameFor(
       IWorkbenchWindow window, Set<IWorkbenchWindow> visitedWindows) {
     IWorkbenchPage activePage = window.getActivePage();
-    StackFrame frame = null;
+    EvaluateContext frame = null;
     // Check the active page in the window
     if (activePage != null) {
       frame = getStackFrameFor(activePage);
@@ -166,7 +168,7 @@
     return null;
   }
 
-  private static StackFrame getStackFrameFor(IWorkbenchPage page) {
+  private static EvaluateContext getStackFrameFor(IWorkbenchPage page) {
     if (instance != null) {
       return instance.pageToFrame.get(page);
     }
@@ -181,7 +183,7 @@
     }
   }
 
-  private void putStackFrame(IWorkbenchPage page, StackFrame frame) {
+  private void putStackFrame(IWorkbenchPage page, EvaluateContext frame) {
     pageToFrame.put(page, frame);
     System.setProperty(DEBUGGER_ACTIVE, Boolean.TRUE.toString());
   }
--- a/org.chromium.debug.ui/src/org/chromium/debug/ui/JsWatchExpressionDelegate.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/JsWatchExpressionDelegate.java	Wed Jan 27 15:59:22 2010 -0800
@@ -6,9 +6,9 @@
 
 import org.chromium.debug.core.ChromiumDebugPlugin;
 import org.chromium.debug.core.model.DebugElementImpl;
-import org.chromium.debug.core.model.StackFrame;
+import org.chromium.debug.core.model.EvaluateContext;
 import org.chromium.debug.core.model.Variable;
-import org.chromium.sdk.CallFrame;
+import org.chromium.sdk.JsEvaluateContext;
 import org.chromium.sdk.JsVariable;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.debug.core.DebugException;
@@ -133,30 +133,34 @@
       });
       return;
     }
-    if (!(contextImpl instanceof StackFrame)) {
+
+    final EvaluateContext evaluateContext =
+        (EvaluateContext) contextImpl.getAdapter(EvaluateContext.class);
+    if (evaluateContext == null) {
       listener.watchEvaluationFinished(new BadWatchExpressionResult(
           new DebugException(
               new Status(Status.ERROR, ChromiumDebugUIPlugin.PLUGIN_ID, "Bad debug context")), //$NON-NLS-1$
           expression));
       return;
     }
-    StackFrame stackFrame = (StackFrame) contextImpl;
-    final CallFrame frame = stackFrame.getCallFrame();
-    frame.evaluateAsync(expression, new CallFrame.EvaluateCallback() {
-        public void success(JsVariable variable) {
-          final Variable var = new Variable(contextImpl.getDebugTarget(), variable, false);
-          listener.watchEvaluationFinished(new GoodWatchExpressionResult(var, expression));
-        }
+
+    evaluateContext.getJsEvaluateContext().evaluateAsync(
+        expression,
+        new JsEvaluateContext.EvaluateCallback() {
+          public void success(JsVariable variable) {
+            final Variable var = new Variable(contextImpl.getDebugTarget(), variable, false);
+            listener.watchEvaluationFinished(new GoodWatchExpressionResult(var, expression));
+          }
 
-        public void failure(String message) {
-          listener.watchEvaluationFinished(new BadWatchExpressionResult(new DebugException(
-              createErrorStatus(message == null
-                  ? Messages.JsWatchExpressionDelegate_ErrorEvaluatingExpression
-                  : message, null)), expression));
-          return;
-        }
-      },
-      null);
+          public void failure(String message) {
+            listener.watchEvaluationFinished(new BadWatchExpressionResult(new DebugException(
+                createErrorStatus(message == null
+                    ? Messages.JsWatchExpressionDelegate_ErrorEvaluatingExpression
+                    : message, null)), expression));
+            return;
+          }
+        },
+        null);
   }
 
   private static Status createErrorStatus(String message, Exception e) {
--- a/org.chromium.debug.ui/src/org/chromium/debug/ui/actions/JsInspectExpression.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/actions/JsInspectExpression.java	Wed Jan 27 15:59:22 2010 -0800
@@ -4,8 +4,8 @@
 
 package org.chromium.debug.ui.actions;
 
-import org.chromium.debug.core.ChromiumDebugPlugin;
-import org.chromium.debug.core.model.StackFrame;
+import org.chromium.debug.core.model.EvaluateContext;
+import org.chromium.debug.core.model.VProjectWorkspaceBridge;
 import org.chromium.debug.core.model.Value;
 import org.chromium.sdk.JsVariable;
 import org.eclipse.core.runtime.PlatformObject;
@@ -24,7 +24,7 @@
 public class JsInspectExpression extends PlatformObject
     implements IErrorReportingExpression, IDebugEventSetListener {
 
-  private final StackFrame stackFrame;
+  private final EvaluateContext evaluateContext;
 
   private final JsVariable variable;
 
@@ -32,9 +32,9 @@
 
   private final String expression;
 
-  public JsInspectExpression(StackFrame stackFrame, String expression, JsVariable variable,
+  public JsInspectExpression(EvaluateContext evaluateContext, String expression, JsVariable variable,
       String errorMessage) {
-    this.stackFrame = stackFrame;
+    this.evaluateContext = evaluateContext;
     this.expression = expression;
     this.variable = variable;
     this.errorMessage = errorMessage;
@@ -67,7 +67,7 @@
 
   public IValue getValue() {
     return variable != null
-        ? Value.create(stackFrame.getDebugTarget(), variable.getValue())
+        ? Value.create(evaluateContext.getDebugTarget(), variable.getValue())
         : null;
   }
 
@@ -76,7 +76,7 @@
   }
 
   public String getModelIdentifier() {
-    return ChromiumDebugPlugin.DEBUG_MODEL_ID;
+    return VProjectWorkspaceBridge.DEBUG_MODEL_ID;
   }
 
   public void handleDebugEvents(DebugEvent[] events) {
--- a/org.chromium.debug.ui/src/org/chromium/debug/ui/actions/JsInspectSnippetAction.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/actions/JsInspectSnippetAction.java	Wed Jan 27 15:59:22 2010 -0800
@@ -4,11 +4,11 @@
 
 package org.chromium.debug.ui.actions;
 
-import org.chromium.debug.core.model.StackFrame;
+import org.chromium.debug.core.model.EvaluateContext;
 import org.chromium.debug.ui.ChromiumDebugUIPlugin;
 import org.chromium.debug.ui.JsEvalContextManager;
 import org.chromium.debug.ui.editors.JavascriptUtil;
-import org.chromium.sdk.CallFrame;
+import org.chromium.sdk.JsEvaluateContext;
 import org.chromium.sdk.JsVariable;
 import org.eclipse.debug.core.model.IExpression;
 import org.eclipse.debug.ui.DebugPopup;
@@ -38,7 +38,8 @@
  * Action for inspecting a JavaScript snippet.
  */
 public class JsInspectSnippetAction implements IEditorActionDelegate,
-    IWorkbenchWindowActionDelegate, IPartListener, IViewActionDelegate, CallFrame.EvaluateCallback {
+    IWorkbenchWindowActionDelegate, IPartListener, IViewActionDelegate,
+    JsEvaluateContext.EvaluateCallback {
 
   private static final String ACTION_DEFINITION_ID = "org.chromium.debug.ui.commands.Inspect"; //$NON-NLS-1$
 
@@ -139,20 +140,21 @@
     return null;
   }
 
-  private StackFrame getStackFrameContext() {
+  private EvaluateContext getStackFrameContext() {
+    // TODO(peter.rybin): consider simply using DebugUITools.getDebugContext()
     IWorkbenchPart part = getTargetPart();
-    return getStackFrameForPart(part);
+    return getEvaluateContextForPart(part);
   }
 
-  private StackFrame getStackFrameForPart(IWorkbenchPart part) {
-    StackFrame frame = part == null
+  private EvaluateContext getEvaluateContextForPart(IWorkbenchPart part) {
+    EvaluateContext frame = part == null
         ? JsEvalContextManager.getStackFrameFor(getWindow())
         : JsEvalContextManager.getStackFrameFor(part);
     return frame;
   }
 
   private void run() {
-    getStackFrameContext().getCallFrame().evaluateAsync(getSelectedText(), this, null);
+    getStackFrameContext().getJsEvaluateContext().evaluateAsync(getSelectedText(), this, null);
   }
 
   protected String getSelectedText() {
--- a/org.chromium.debug.ui/src/org/chromium/debug/ui/actions/OpenFunctionAction.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/actions/OpenFunctionAction.java	Wed Jan 27 15:59:22 2010 -0800
@@ -63,7 +63,7 @@
         if (script == null) {
           return;
         }
-        IFile resource = variable.getDebugTarget().getResourceManager().getResource(script);
+        IFile resource = variable.getDebugTarget().getScriptResource(script);
         IEditorInput input = JsDebugModelPresentation.toEditorInput(resource);
         IEditorPart editor;
         try {
--- a/org.chromium.debug.ui/src/org/chromium/debug/ui/editors/JsDebugTextHover.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/editors/JsDebugTextHover.java	Wed Jan 27 15:59:22 2010 -0800
@@ -4,9 +4,9 @@
 
 package org.chromium.debug.ui.editors;
 
-import org.chromium.debug.core.model.StackFrame;
+import org.chromium.debug.core.model.EvaluateContext;
 import org.chromium.debug.core.util.JsValueStringifier;
-import org.chromium.sdk.CallFrame;
+import org.chromium.sdk.JsEvaluateContext;
 import org.chromium.sdk.JsVariable;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.debug.ui.DebugUITools;
@@ -34,19 +34,20 @@
       return null;
     }
 
-    StackFrame frame = (StackFrame) context.getAdapter(StackFrame.class);
-    if (frame == null) { // not a stackframe-related context
+    EvaluateContext evaluateContext = (EvaluateContext) context.getAdapter(EvaluateContext.class);
+    if (evaluateContext == null) {
       return null;
     }
 
     final JsVariable[] result = new JsVariable[1];
-    frame.getCallFrame().evaluateSync(expression, new CallFrame.EvaluateCallback() {
-      public void success(JsVariable var) {
-        result[0] = var;
-      }
-      public void failure(String errorMessage) {
-      }
-    });
+    evaluateContext.getJsEvaluateContext().evaluateSync(expression,
+        new JsEvaluateContext.EvaluateCallback() {
+          public void success(JsVariable var) {
+            result[0] = var;
+          }
+          public void failure(String errorMessage) {
+          }
+        });
     if (result[0] == null) {
       return null;
     }
--- a/org.chromium.debug.ui/src/org/chromium/debug/ui/launcher/LaunchTypeBase.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/launcher/LaunchTypeBase.java	Wed Jan 27 15:59:22 2010 -0800
@@ -13,6 +13,8 @@
 import org.chromium.debug.core.model.DestructingGuard;
 import org.chromium.debug.core.model.JavascriptVmEmbedder;
 import org.chromium.debug.core.model.NamedConnectionLoggerFactory;
+import org.chromium.debug.core.model.VProjectWorkspaceBridge;
+import org.chromium.debug.core.model.WorkspaceBridge;
 import org.chromium.debug.ui.PluginUtil;
 import org.chromium.sdk.ConnectionLogger;
 import org.eclipse.core.runtime.CoreException;
@@ -38,20 +40,20 @@
     if (!mode.equals(ILaunchManager.DEBUG_MODE)) {
       // Chromium JavaScript launch is only supported for debugging.
       return;
-    } 
-    
+    }
+
     int port =
         config.getAttribute(LaunchTypeBase.CHROMIUM_DEBUG_PORT,
             PluginVariablesUtil.getValueAsInt(PluginVariablesUtil.DEFAULT_PORT));
 
     boolean addNetworkConsole = config.getAttribute(LaunchTypeBase.ADD_NETWORK_CONSOLE, false);
-  
+
     JavascriptVmEmbedder.ConnectionToRemote remoteServer =
         createConnectionToRemote(port, launch, addNetworkConsole);
     try {
-  
-      String projectNameBase = config.getName();
-  
+
+      final String projectNameBase = config.getName();
+
       DestructingGuard destructingGuard = new DestructingGuard();
       try {
         Destructable lauchDestructor = new Destructable() {
@@ -61,41 +63,37 @@
             }
           }
         };
-  
+
         destructingGuard.addValue(lauchDestructor);
-  
-        final DebugTargetImpl target = new DebugTargetImpl(launch);
-  
+
+        WorkspaceBridge.Factory bridgeFactory =
+            new VProjectWorkspaceBridge.FactoryImpl(projectNameBase);
+
+        final DebugTargetImpl target = new DebugTargetImpl(launch, bridgeFactory);
+
         Destructable targetDestructor = new Destructable() {
           public void destruct() {
             terminateTarget(target);
           }
         };
         destructingGuard.addValue(targetDestructor);
-        boolean attached = target.attach(
-            projectNameBase, remoteServer, destructingGuard,
-            new Runnable() {
-              public void run() {
-                PluginUtil.openProjectExplorerView();
-              }
-            },
-            monitor);
+
+        boolean attached = target.attach(remoteServer, destructingGuard,
+            OPENING_VIEW_ATTACH_CALLBACK, monitor);
         if (!attached) {
           // Error
           return;
         }
-  
-        launch.setSourceLocator(target.getSourceLocator());
-  
+
         launch.addDebugTarget(target);
         monitor.done();
-  
+
         // All OK
         destructingGuard.discharge();
       } finally {
         destructingGuard.doFinally();
       }
-  
+
     } finally {
       remoteServer.disposeConnection();
     }
@@ -149,4 +147,10 @@
       return null;
     }
   };
+
+  private static final Runnable OPENING_VIEW_ATTACH_CALLBACK = new Runnable() {
+    public void run() {
+      PluginUtil.openProjectExplorerView();
+    }
+  };
 }
\ No newline at end of file
--- a/org.chromium.sdk/META-INF/MANIFEST.MF	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/META-INF/MANIFEST.MF	Wed Jan 27 15:59:22 2010 -0800
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Google Chrome Developer Tools SDK
 Bundle-SymbolicName: org.chromium.sdk
-Bundle-Version: 0.1.3.qualifier
+Bundle-Version: 0.1.5.qualifier
 Bundle-Vendor: The Chromium Authors
 Bundle-ClassPath: lib/json_simple/json_simple-1.1.jar,
  .
--- a/org.chromium.sdk/src/org/chromium/sdk/CallFrame.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/CallFrame.java	Wed Jan 27 15:59:22 2010 -0800
@@ -7,24 +7,12 @@
 import java.util.Collection;
 import java.util.List;
 
-import org.chromium.sdk.internal.tools.v8.MethodIsBlockingException;
-
-
 /**
  * An object that represents a browser JavaScript VM call frame.
  */
 public interface CallFrame {
 
   /**
-   * A callback for the "evaluate" request.
-   */
-  interface EvaluateCallback {
-    void success(JsVariable variable);
-
-    void failure(String errorMessage);
-  }
-
-  /**
    * @return the variables known in this frame, including the receiver variable
    * @deprecated in favor of {@link #getVariableScopes()}
    */
@@ -72,29 +60,7 @@
   String getFunctionName();
 
   /**
-   * Synchronously evaluates an arbitrary JavaScript {@code expression} in
-   * the context of the call frame. The evaluation result is reported to
-   * the specified {@code evaluateCallback}. The method will block until the evaluation
-   * result is available.
-   *
-   * @param expression to evaluate
-   * @param evaluateCallback to report the evaluation result to
-   * @throws MethodIsBlockingException if called from a callback because it blocks
-   *         until remote VM returns result
+   * @return context for evaluating expressions in scope of this frame
    */
-  void evaluateSync(String expression, EvaluateCallback evaluateCallback)
-      throws MethodIsBlockingException;
-
-  /**
-   * Asynchronously evaluates an arbitrary JavaScript {@code expression} in
-   * the context of the call frame. The evaluation result is reported to
-   * the specified {@code evaluateCallback} and right after this to syncCallback.
-   * The method doesn't block.
-   *
-   * @param expression to evaluate
-   * @param evaluateCallback to report the evaluation result to
-   * @param syncCallback to report the end of any processing
-   */
-  void evaluateAsync(String expression, EvaluateCallback evaluateCallback,
-      SyncCallback syncCallback);
+  JsEvaluateContext getEvaluateContext();
 }
--- a/org.chromium.sdk/src/org/chromium/sdk/ConnectionLogger.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/ConnectionLogger.java	Wed Jan 27 15:59:22 2010 -0800
@@ -4,7 +4,6 @@
 
 package org.chromium.sdk;
 
-import java.io.Reader;
 import java.io.Writer;
 
 /**
@@ -21,14 +20,14 @@
    * @return new writer that should pass all data to {@code streamWriter} and
    * silently copy it elsewhere (without additional exceptions).
    */
-  Writer wrapWriter(Writer streamWriter);
+  LoggableWriter wrapWriter(LoggableWriter streamWriter);
 
   /**
    * @return new reader that should give access to all data
    * from {@code streamReader} and silently copy it elsewhere (without
    * additional exceptions).
    */
-  Reader wrapReader(Reader streamReader);
+  LoggableReader wrapReader(LoggableReader streamReader);
 
   /**
    * Connection may allow the logger to close it. It is nice for UI, where
@@ -65,4 +64,30 @@
      */
     ConnectionLogger newConnectionLogger();
   }
+
+  /**
+   * Reader that allows client to add marks to stream. These marks may become visible in log
+   * console.
+   */
+  interface LoggableReader {
+    LineReader getReader();
+
+    /**
+     * Add log mark at current reader's position.
+     */
+    void markSeparatorForLog();
+  }
+
+  /**
+   * Writer that allows client to add marks to stream. These marks may become visible in log
+   * console.
+   */
+  interface LoggableWriter {
+    Writer getWriter();
+
+    /**
+     * Add log mark at current writer's position.
+     */
+    void markSeparatorForLog();
+  }
 }
--- a/org.chromium.sdk/src/org/chromium/sdk/DebugContext.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/DebugContext.java	Wed Jan 27 15:59:22 2010 -0800
@@ -103,4 +103,8 @@
    */
   void continueVm(StepAction stepAction, int stepCount, ContinueCallback callback);
 
+  /**
+   * @return evaluate context for evaluating expressions in global scope
+   */
+  JsEvaluateContext getGlobalEvaluateContext();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.sdk/src/org/chromium/sdk/JsEvaluateContext.java	Wed Jan 27 15:59:22 2010 -0800
@@ -0,0 +1,50 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.sdk;
+
+import org.chromium.sdk.internal.tools.v8.MethodIsBlockingException;
+
+/**
+ * A context in which watch expressions may be evaluated. Typically corresponds to stack frame
+ * of suspended process, but may also be detached from any stack frame.
+ */
+public interface JsEvaluateContext {
+
+  /**
+   * A callback for the "evaluate" request.
+   */
+  interface EvaluateCallback {
+    void success(JsVariable variable);
+
+    void failure(String errorMessage);
+  }
+
+  /**
+   * Synchronously evaluates an arbitrary JavaScript {@code expression} in
+   * the context of the call frame. The evaluation result is reported to
+   * the specified {@code evaluateCallback}. The method will block until the evaluation
+   * result is available.
+   *
+   * @param expression to evaluate
+   * @param evaluateCallback to report the evaluation result to
+   * @throws MethodIsBlockingException if called from a callback because it blocks
+   *         until remote VM returns result
+   */
+  void evaluateSync(String expression, EvaluateCallback evaluateCallback)
+      throws MethodIsBlockingException;
+
+  /**
+   * Asynchronously evaluates an arbitrary JavaScript {@code expression} in
+   * the context of the call frame. The evaluation result is reported to
+   * the specified {@code evaluateCallback} and right after this to syncCallback.
+   * The method doesn't block.
+   *
+   * @param expression to evaluate
+   * @param evaluateCallback to report the evaluation result to
+   * @param syncCallback to report the end of any processing
+   */
+  void evaluateAsync(String expression, EvaluateCallback evaluateCallback,
+      SyncCallback syncCallback);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.sdk/src/org/chromium/sdk/LineReader.java	Wed Jan 27 15:59:22 2010 -0800
@@ -0,0 +1,23 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.sdk;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+
+/**
+ * Lets read lines similar to BufferedReader, but does not buffer.
+ */
+public interface LineReader {
+  /**
+   * Method has similar semantics to {@link BufferedReader#read(char[], int, int)} method.
+   */
+  int read(char[] cbuf, int off, int len) throws IOException;
+
+  /**
+   * Method has similar semantics to {@link BufferedReader#readLine()} method.
+   */
+  String readLine() throws IOException;
+}
\ No newline at end of file
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/CallFrameImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/CallFrameImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -10,21 +10,10 @@
 import java.util.List;
 
 import org.chromium.sdk.CallFrame;
-import org.chromium.sdk.CallbackSemaphore;
+import org.chromium.sdk.JsEvaluateContext;
 import org.chromium.sdk.JsScope;
 import org.chromium.sdk.JsVariable;
 import org.chromium.sdk.Script;
-import org.chromium.sdk.SyncCallback;
-import org.chromium.sdk.internal.InternalContext.ContextDismissedCheckedException;
-import org.chromium.sdk.internal.protocol.CommandResponse;
-import org.chromium.sdk.internal.protocol.SuccessCommandResponse;
-import org.chromium.sdk.internal.protocol.data.ValueHandle;
-import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;
-import org.chromium.sdk.internal.tools.v8.MethodIsBlockingException;
-import org.chromium.sdk.internal.tools.v8.V8CommandProcessor;
-import org.chromium.sdk.internal.tools.v8.V8Helper;
-import org.chromium.sdk.internal.tools.v8.request.DebuggerMessage;
-import org.chromium.sdk.internal.tools.v8.request.DebuggerMessageFactory;
 
 /**
  * A generic implementation of the CallFrame interface.
@@ -84,6 +73,10 @@
     return this.receiverVariable;
   }
 
+  public JsEvaluateContext getEvaluateContext() {
+    return evaluateContextImpl;
+  }
+
   private void ensureVariables() {
     if (variables == null) {
       this.variables = Collections.unmodifiableCollection(createVariables());
@@ -105,7 +98,7 @@
         ValueLoader valueLoader = context.getValueLoader();
         ValueMirror mirror =
             valueLoader.getOrLoadValueFromRefs(Collections.singletonList(ref)).get(0);
-        this.receiverVariable = new JsVariableImpl(this, mirror, ref.getName());
+        this.receiverVariable = new JsVariableImpl(this.context, mirror, ref.getName());
       }
       this.receiverVariableLoaded = true;
     }
@@ -136,69 +129,6 @@
     return frameMirror.getScript();
   }
 
-  public void evaluateSync(String expression, EvaluateCallback evaluateCallback)
-      throws MethodIsBlockingException {
-    CallbackSemaphore callbackSemaphore = new CallbackSemaphore();
-    evaluateAsync(expression, evaluateCallback, callbackSemaphore);
-    boolean res = callbackSemaphore.tryAcquireDefault();
-    if (!res) {
-      evaluateCallback.failure("Timeout");
-    }
-  }
-
-  public void evaluateAsync(final String expression, final EvaluateCallback callback,
-      SyncCallback syncCallback) {
-    try {
-      evaluateAsyncImpl(expression, callback, syncCallback);
-    } catch (ContextDismissedCheckedException e) {
-      getInternalContext().getDebugSession().maybeRethrowContextException(e);
-      // or
-      try {
-        callback.failure(e.getMessage());
-      } finally {
-        syncCallback.callbackDone(null);
-      }
-    }
-  }
-  public void evaluateAsyncImpl(final String expression, final EvaluateCallback callback,
-      SyncCallback syncCallback) throws ContextDismissedCheckedException {
-    DebuggerMessage message =
-      DebuggerMessageFactory.evaluate(expression, getIdentifier(), null, null);
-
-    V8CommandProcessor.V8HandlerCallback commandCallback = callback == null
-        ? null
-        : new V8CommandProcessor.V8HandlerCallback() {
-          public void messageReceived(CommandResponse response) {
-            SuccessCommandResponse successResponse = response.asSuccess();
-            if (successResponse != null) {
-              ValueHandle body;
-              try {
-                body = successResponse.getBody().asEvaluateBody();
-              } catch (JsonProtocolParseException e) {
-                throw new RuntimeException(e);
-              }
-              JsVariable variable =
-                  new JsVariableImpl(CallFrameImpl.this, V8Helper.createMirrorFromLookup(
-                      body).getValueMirror(), expression);
-              if (variable != null) {
-                callback.success(variable);
-              } else {
-                callback.failure("Evaluation failed");
-              }
-            } else {
-              callback.failure(response.asFailure().getMessage());
-            }
-          }
-
-          public void failure(String message) {
-            callback.failure(message);
-          }
-        };
-
-    getInternalContext().sendV8CommandAsync(message, true, commandCallback,
-        syncCallback);
-  }
-
   /**
    * @return this call frame's unique identifier within the V8 VM (0 is the top
    *         frame)
@@ -215,7 +145,7 @@
     List<ValueMirror> mirrors = context.getValueLoader().getOrLoadValueFromRefs(refs);
     Collection<JsVariableImpl> result = new ArrayList<JsVariableImpl>(refs.size());
     for (int i = 0; i < refs.size(); i++) {
-      result.add(new JsVariableImpl(this, mirrors.get(i), refs.get(i).getName()));
+      result.add(new JsVariableImpl(this.context, mirrors.get(i), refs.get(i).getName()));
     }
     return result;
   }
@@ -228,4 +158,15 @@
     }
     return result;
   }
+
+  private final JsEvaluateContextImpl evaluateContextImpl = new JsEvaluateContextImpl() {
+    @Override
+    protected Integer getFrameIdentifier() {
+      return getIdentifier();
+    }
+    @Override
+    public InternalContext getInternalContext() {
+      return context;
+    }
+  };
 }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/ContextBuilder.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/ContextBuilder.java	Wed Jan 27 15:59:22 2010 -0800
@@ -13,6 +13,7 @@
 import org.chromium.sdk.CallFrame;
 import org.chromium.sdk.DebugContext;
 import org.chromium.sdk.ExceptionData;
+import org.chromium.sdk.JsEvaluateContext;
 import org.chromium.sdk.Script;
 import org.chromium.sdk.SyncCallback;
 import org.chromium.sdk.internal.protocol.CommandResponse;
@@ -265,6 +266,10 @@
         return data.exceptionData;
       }
 
+      public JsEvaluateContext getGlobalEvaluateContext() {
+        return evaluateContext;
+      }
+
       /**
        * @throws IllegalStateException if context has already been continued
        */
@@ -308,6 +313,17 @@
       InternalContext getInternalContextForTests() {
         return PreContext.this;
       }
+
+      private final JsEvaluateContext evaluateContext = new JsEvaluateContextImpl() {
+        @Override
+        protected Integer getFrameIdentifier() {
+          return null;
+        }
+        @Override
+        public InternalContext getInternalContext() {
+          return PreContext.this;
+        }
+      };
     }
   }
 
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/ExceptionDataImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/ExceptionDataImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -32,7 +32,8 @@
 
   public JsObject getExceptionObject() {
     if (cachedException == null) {
-      cachedException = new JsObjectImpl(context.getTopFrameImpl(), name, mirror);
+      cachedException =
+          new JsObjectImpl(context.getTopFrameImpl().getInternalContext(), name, mirror);
     }
     return cachedException;
   }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JsArrayImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsArrayImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -28,12 +28,12 @@
   /**
    * This constructor implies lazy resolution of object properties.
    *
-   * @param callFrame this array belongs in
+   * @param context this array belongs in
    * @param parentFqn the fully qualified name of this array parent
    * @param valueState the mirror corresponding to this array
    */
-  JsArrayImpl(CallFrameImpl callFrame, String parentFqn, ValueMirror valueState) {
-    super(callFrame, parentFqn, valueState);
+  JsArrayImpl(InternalContext context, String parentFqn, ValueMirror valueState) {
+    super(context, parentFqn, valueState);
   }
 
   private synchronized void ensureElementsMap() throws MethodIsBlockingException {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsEvaluateContextImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -0,0 +1,100 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.sdk.internal;
+
+import org.chromium.sdk.CallbackSemaphore;
+import org.chromium.sdk.JsEvaluateContext;
+import org.chromium.sdk.JsVariable;
+import org.chromium.sdk.SyncCallback;
+import org.chromium.sdk.internal.InternalContext.ContextDismissedCheckedException;
+import org.chromium.sdk.internal.protocol.CommandResponse;
+import org.chromium.sdk.internal.protocol.SuccessCommandResponse;
+import org.chromium.sdk.internal.protocol.data.ValueHandle;
+import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;
+import org.chromium.sdk.internal.tools.v8.MethodIsBlockingException;
+import org.chromium.sdk.internal.tools.v8.V8CommandProcessor;
+import org.chromium.sdk.internal.tools.v8.V8Helper;
+import org.chromium.sdk.internal.tools.v8.request.DebuggerMessage;
+import org.chromium.sdk.internal.tools.v8.request.DebuggerMessageFactory;
+
+/**
+ * Generic implementation of {@link JsEvaluateContext}. The abstract class leaves unspecified
+ * stack frame identifier (possibly null) and reference to {@link InternalContext}.
+ */
+abstract class JsEvaluateContextImpl implements JsEvaluateContext {
+  public void evaluateSync(String expression, EvaluateCallback evaluateCallback)
+      throws MethodIsBlockingException {
+    CallbackSemaphore callbackSemaphore = new CallbackSemaphore();
+    evaluateAsync(expression, evaluateCallback, callbackSemaphore);
+    boolean res = callbackSemaphore.tryAcquireDefault();
+    if (!res) {
+      evaluateCallback.failure("Timeout");
+    }
+  }
+
+  public void evaluateAsync(final String expression, final EvaluateCallback callback,
+      SyncCallback syncCallback) {
+    try {
+      evaluateAsyncImpl(expression, callback, syncCallback);
+    } catch (ContextDismissedCheckedException e) {
+      getInternalContext().getDebugSession().maybeRethrowContextException(e);
+      // or
+      try {
+        callback.failure(e.getMessage());
+      } finally {
+        syncCallback.callbackDone(null);
+      }
+    }
+  }
+
+  public void evaluateAsyncImpl(final String expression, final EvaluateCallback callback,
+      SyncCallback syncCallback) throws ContextDismissedCheckedException {
+
+    Integer frameIdentifier = getFrameIdentifier();
+    Boolean isGlobal = frameIdentifier == null ? Boolean.TRUE : null;
+    DebuggerMessage message =
+        DebuggerMessageFactory.evaluate(expression, frameIdentifier, isGlobal, Boolean.TRUE);
+
+    V8CommandProcessor.V8HandlerCallback commandCallback = callback == null
+        ? null
+        : new V8CommandProcessor.V8HandlerCallback() {
+          public void messageReceived(CommandResponse response) {
+            SuccessCommandResponse successResponse = response.asSuccess();
+            if (successResponse != null) {
+              ValueHandle body;
+              try {
+                body = successResponse.getBody().asEvaluateBody();
+              } catch (JsonProtocolParseException e) {
+                throw new RuntimeException(e);
+              }
+              JsVariable variable =
+                  new JsVariableImpl(JsEvaluateContextImpl.this.getInternalContext(),
+                      V8Helper.createMirrorFromLookup(body).getValueMirror(), expression);
+              if (variable != null) {
+                callback.success(variable);
+              } else {
+                callback.failure("Evaluation failed");
+              }
+            } else {
+              callback.failure(response.asFailure().getMessage());
+            }
+          }
+
+          public void failure(String message) {
+            callback.failure(message);
+          }
+        };
+
+    getInternalContext().sendV8CommandAsync(message, true, commandCallback,
+        syncCallback);
+  }
+
+  /**
+   * @return frame identifier or null if the context is not frame-related
+   */
+  protected abstract Integer getFrameIdentifier();
+
+  protected abstract InternalContext getInternalContext();
+}
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JsFunctionImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsFunctionImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -11,8 +11,8 @@
  * Generic implementation of {@link JsFunction}.
  */
 class JsFunctionImpl extends JsObjectImpl implements JsFunction {
-  JsFunctionImpl(CallFrameImpl callFrame, String parentFqn, ValueMirror valueState) {
-    super(callFrame, parentFqn, valueState);
+  JsFunctionImpl(InternalContext context, String parentFqn, ValueMirror valueState) {
+    super(context, parentFqn, valueState);
   }
 
   public Script getScript() {
@@ -23,7 +23,7 @@
     if (scriptId == FunctionAdditionalProperties.NO_SCRIPT_ID) {
       return null;
     }
-    DebugSession debugSession = getCallFrame().getInternalContext().getDebugSession();
+    DebugSession debugSession = getInternalContext().getDebugSession();
     return debugSession.getScriptManager().findById(Long.valueOf(scriptId));
   }
 
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JsObjectImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsObjectImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -21,20 +21,20 @@
  */
 class JsObjectImpl extends JsValueImpl implements JsObject {
 
-  private final CallFrameImpl callFrame;
+  private final InternalContext context;
 
   private final String parentFqn;
 
   /**
    * This constructor implies the lazy resolution of object properties.
    *
-   * @param callFrame where this instance belongs in
+   * @param context where this instance belongs in
    * @param parentFqn the fully qualified name of the object parent
    * @param valueState the value data from the JS VM
    */
-  JsObjectImpl(CallFrameImpl callFrame, String parentFqn, ValueMirror valueState) {
+  JsObjectImpl(InternalContext context, String parentFqn, ValueMirror valueState) {
     super(valueState);
-    this.callFrame = callFrame;
+    this.context = context;
     this.parentFqn = parentFqn;
   }
 
@@ -96,8 +96,8 @@
     return JsVariableImpl.NameDecorator.NOOP;
   }
 
-  protected CallFrameImpl getCallFrame() {
-    return callFrame;
+  protected InternalContext getInternalContext() {
+    return context;
   }
 
   Subproperties getSubpropertiesHelper() {
@@ -105,9 +105,7 @@
   }
 
   protected SubpropertiesMirror getSubpropertiesMirror() {
-    ValueLoader valueLoader = callFrame.getInternalContext().getValueLoader();
-
-    return valueLoader.loadSubpropertiesInMirror(getMirror()).getSubpropertiesMirror();
+    return context.getValueLoader().loadSubpropertiesInMirror(getMirror()).getSubpropertiesMirror();
   }
 
   abstract class Subproperties {
@@ -143,7 +141,7 @@
         if (fqn == null) {
           continue;
         }
-        result.add(new JsVariableImpl(callFrame, mirror, varName, fqn,
+        result.add(new JsVariableImpl(context, mirror, varName, fqn,
             getNameDecorator()));
       }
       return result;
@@ -166,7 +164,7 @@
         if (properties == null) {
 
         List<? extends PropertyReference> propertyRefs = getPropertyRefs(getSubpropertiesMirror());
-        ValueLoader valueLoader = callFrame.getInternalContext().getValueLoader();
+        ValueLoader valueLoader = context.getValueLoader();
         List<ValueMirror> subMirrors = valueLoader.getOrLoadValueFromRefs(propertyRefs);
 
           List<JsVariableImpl> wrappedProperties = createPropertiesFromMirror(subMirrors,
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JsScopeImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsScopeImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -43,8 +43,8 @@
 
       properties = new ArrayList<JsVariable>(propertyMirrors.size());
       for (int i = 0; i < propertyMirrors.size(); i++) {
-        properties.add(new JsVariableImpl(callFrameImpl, propertyMirrors.get(i),
-            propertyRefs.get(i).getName()));
+        properties.add(new JsVariableImpl(callFrameImpl.getInternalContext(),
+            propertyMirrors.get(i), propertyRefs.get(i).getName()));
       }
     }
     return properties;
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JsVariableImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsVariableImpl.java	Wed Jan 27 15:59:22 2010 -0800
@@ -19,8 +19,8 @@
    */
   private final ValueMirror valueData;
 
-  /** The call frame this variable belongs in. */
-  private final CallFrameImpl callFrame;
+  /** The context this variable belongs in. */
+  private final InternalContext context;
 
   /** The fully qualified name of this variable. */
   private final String variableFqn;
@@ -34,27 +34,27 @@
   private final String rawName;
 
   /**
-   * Constructs a variable contained in the given call frame with the given
+   * Constructs a variable contained in the given context with the given
    * value mirror.
    *
-   * @param callFrame that owns this variable
+   * @param context that owns this variable
    * @param valueData value data for this variable
    */
-  JsVariableImpl(CallFrameImpl callFrame, ValueMirror valueData, String name) {
-    this(callFrame, valueData, name, null, NameDecorator.NOOP);
+  JsVariableImpl(InternalContext context, ValueMirror valueData, String name) {
+    this(context, valueData, name, null, NameDecorator.NOOP);
   }
 
   /**
-   * Constructs a variable contained in the given call frame with the given
+   * Constructs a variable contained in the given context with the given
    * value mirror.
    *
-   * @param callFrame that owns this variable
+   * @param context that owns this variable
    * @param valueData for this variable
    * @param variableFqn the fully qualified name of this variable
    */
-  JsVariableImpl(CallFrameImpl callFrame, ValueMirror valueData, String name, String variableFqn,
+  JsVariableImpl(InternalContext context, ValueMirror valueData, String name, String variableFqn,
       NameDecorator nameDecorator) {
-    this.callFrame = callFrame;
+    this.context = context;
     this.valueData = valueData;
     this.rawName = name;
     this.variableFqn = variableFqn;
@@ -63,14 +63,14 @@
     Type type = this.valueData.getType();
     switch (type) {
       case TYPE_FUNCTION:
-        this.value = new JsFunctionImpl(callFrame, this.variableFqn, this.valueData);
+        this.value = new JsFunctionImpl(context, this.variableFqn, this.valueData);
         break;
       case TYPE_ERROR:
       case TYPE_OBJECT:
-        this.value = new JsObjectImpl(callFrame, this.variableFqn, this.valueData);
+        this.value = new JsObjectImpl(context, this.variableFqn, this.valueData);
         break;
       case TYPE_ARRAY:
-        this.value = new JsArrayImpl(callFrame, this.variableFqn, this.valueData);
+        this.value = new JsArrayImpl(context, this.variableFqn, this.valueData);
         break;
       default:
         this.value = new JsValueImpl(this.valueData);
@@ -121,10 +121,10 @@
   }
 
   /**
-   * Returns the call frame owning this variable.
+   * Returns the context owning this variable.
    */
-  protected CallFrameImpl getCallFrame() {
-    return callFrame;
+  protected InternalContext getInternalContext() {
+    return context;
   }
 
   public ValueMirror getMirror() {
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/protocol/BacktraceCommandBody.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/protocol/BacktraceCommandBody.java	Wed Jan 27 15:59:22 2010 -0800
@@ -12,7 +12,7 @@
 
 @JsonType
 public interface BacktraceCommandBody extends JsonSubtype<CommandResponseBody> {
-
+  @JsonOptionalField
   List<FrameObject> getFrames();
 
   @JsonOptionalField
@@ -21,6 +21,5 @@
   @JsonOptionalField
   Long toFrame();
 
-  @JsonOptionalField
   Long totalFrames();
 }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/processor/BacktraceProcessor.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/processor/BacktraceProcessor.java	Wed Jan 27 15:59:22 2010 -0800
@@ -5,6 +5,7 @@
 package org.chromium.sdk.internal.tools.v8.processor;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -74,6 +75,9 @@
       throw new RuntimeException(e);
     }
     List<FrameObject> jsonFrames = body.getFrames();
+    if (jsonFrames == null) {
+      jsonFrames = Collections.emptyList();
+    }
     int frameCnt = jsonFrames.size();
     FrameMirror[] frameMirrors = new FrameMirror[frameCnt];
 
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/request/EvaluateMessage.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/request/EvaluateMessage.java	Wed Jan 27 15:59:22 2010 -0800
@@ -21,7 +21,9 @@
       Boolean global, Boolean disableBreak) {
     super(DebuggerCommand.EVALUATE.value);
     putArgument("expression", expression);
-    putArgument("frame", frame);
+    if (frame != null) {
+      putArgument("frame", frame);
+    }
     putArgument("global", global);
     putArgument("disable_break", disableBreak);
     putArgument("inlineRefs", Boolean.TRUE);
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/transport/Handshaker.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/transport/Handshaker.java	Wed Jan 27 15:59:22 2010 -0800
@@ -4,7 +4,6 @@
 
 package org.chromium.sdk.internal.transport;
 
-import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.Writer;
 import java.util.concurrent.Callable;
@@ -13,6 +12,7 @@
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.RunnableFuture;
 
+import org.chromium.sdk.LineReader;
 import org.chromium.sdk.internal.transport.Message.MalformedMessageException;
 
 /**
@@ -27,14 +27,14 @@
    * @throws IOException if handshake process failed physically (input or output has unexpectedly
    * closed) or logically (if unexpected message came from remote).
    */
-  void perform(BufferedReader input, Writer output) throws IOException;
+  void perform(LineReader input, Writer output) throws IOException;
 
   /**
    * Implementation of handshake from Google Chrome Developer Tools Protocol. Used when we
    * connect to browser.
    */
   Handshaker CHROMIUM = new Handshaker() {
-    public void perform(BufferedReader input, Writer output) throws IOException {
+    public void perform(LineReader input, Writer output) throws IOException {
       output.write(OUTGOING_MESSAGE);
       output.flush();
 
@@ -88,9 +88,9 @@
     private final RunnableFuture<RemoteInfo> runnableFuture =
         new FutureTask<RemoteInfo>(new HandshakeTaks());
 
-    private BufferedReader input = null;
+    private LineReader input = null;
 
-    public void perform(BufferedReader input, Writer output) throws IOException {
+    public void perform(LineReader input, Writer output) throws IOException {
       this.input = input;
       runnableFuture.run();
 
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/transport/Message.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/transport/Message.java	Wed Jan 27 15:59:22 2010 -0800
@@ -4,7 +4,6 @@
 
 package org.chromium.sdk.internal.transport;
 
-import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
@@ -13,6 +12,8 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.chromium.sdk.LineReader;
+
 /**
  * A transport message encapsulating the data sent/received over the wire
  * (protocol headers and content). This class can serialize and deserialize
@@ -113,7 +114,7 @@
    * @throws MalformedMessageException if the input does not represent a valid
    *         message
    */
-  public static Message fromBufferedReader(BufferedReader reader)
+  public static Message fromBufferedReader(LineReader reader)
       throws IOException, MalformedMessageException {
     Map<String, String> headers = new HashMap<String, String>();
     synchronized (reader) {
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/transport/SocketConnection.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/transport/SocketConnection.java	Wed Jan 27 15:59:22 2010 -0800
@@ -20,6 +20,7 @@
 import java.util.logging.Logger;
 
 import org.chromium.sdk.ConnectionLogger;
+import org.chromium.sdk.LineReader;
 import org.chromium.sdk.internal.transport.Message.MalformedMessageException;
 
 /**
@@ -67,9 +68,9 @@
    */
   private class WriterThread extends InterruptibleThread {
 
-    private final BufferedWriter writer;
+    private final ConnectionLogger.LoggableWriter writer;
 
-    public WriterThread(BufferedWriter writer) {
+    public WriterThread(ConnectionLogger.LoggableWriter writer) {
       super("WriterThread");
       this.writer = writer;
     }
@@ -88,7 +89,8 @@
     private void handleOutboundMessage(Message message) {
       try {
         LOGGER.log(Level.FINER, "-->{0}", message);
-        message.sendThrough(writer);
+        message.sendThrough(writer.getWriter());
+        writer.markSeparatorForLog();
       } catch (IOException e) {
         SocketConnection.this.shutdown(e, false);
       }
@@ -131,10 +133,11 @@
    */
   private class ReaderThread extends InterruptibleThread {
 
-    private final BufferedReader reader;
-    private final Writer handshakeWriter;
+    private final ConnectionLogger.LoggableReader reader;
+    private final ConnectionLogger.LoggableWriter handshakeWriter;
 
-    public ReaderThread(BufferedReader reader, Writer handshakeWriter) {
+    public ReaderThread(ConnectionLogger.LoggableReader reader,
+        ConnectionLogger.LoggableWriter handshakeWriter) {
       super("ReaderThread");
       this.reader = reader;
       this.handshakeWriter = handshakeWriter;
@@ -151,14 +154,17 @@
           connectionLogger.start();
         }
 
-        handshaker.perform(reader, handshakeWriter);
+        handshaker.perform(reader.getReader(), handshakeWriter.getWriter());
+
+        reader.markSeparatorForLog();
+        handshakeWriter.markSeparatorForLog();
 
         startWriterThread();
 
         while (!isTerminated && isAttached.get()) {
           Message message;
           try {
-            message = Message.fromBufferedReader(reader);
+            message = Message.fromBufferedReader(reader.getReader());
           } catch (MalformedMessageException e) {
             LOGGER.log(Level.SEVERE, "Malformed protocol message", e);
             continue;
@@ -168,6 +174,7 @@
             break;
           }
           inboundQueue.add(new RegularMessageItem(message));
+          reader.markSeparatorForLog();
         }
         breakException = null;
       } catch (IOException e) {
@@ -238,13 +245,13 @@
   private AtomicBoolean isAttached = new AtomicBoolean(false);
 
   /** The communication socket. */
-  protected Socket socket;
+  private Socket socket;
 
   /** The socket reader. */
-  protected BufferedReader reader;
+  private ConnectionLogger.LoggableReader reader;
 
   /** The socket writer. */
-  protected BufferedWriter writer;
+  private ConnectionLogger.LoggableWriter writer;
 
   private final ConnectionLogger connectionLogger;
 
@@ -252,13 +259,13 @@
   private final Handshaker handshaker;
 
   /** The listener to report network events to. */
-  protected volatile NetListener listener;
+  private volatile NetListener listener;
 
   /** The inbound message queue. */
-  protected final BlockingQueue<MessageItem> inboundQueue = new LinkedBlockingQueue<MessageItem>();
+  private final BlockingQueue<MessageItem> inboundQueue = new LinkedBlockingQueue<MessageItem>();
 
   /** The outbound message queue. */
-  protected final BlockingQueue<Message> outboundQueue = new LinkedBlockingQueue<Message>();
+  private final BlockingQueue<Message> outboundQueue = new LinkedBlockingQueue<Message>();
 
   /** The socket endpoint. */
   private final SocketAddress socketEndpoint;
@@ -283,12 +290,44 @@
   void attach() throws IOException {
     this.socket = new Socket();
     this.socket.connect(socketEndpoint, connectionTimeoutMs);
-    Writer streamWriter = new OutputStreamWriter(socket.getOutputStream(), SOCKET_CHARSET);
-    Reader streamReader = new InputStreamReader(socket.getInputStream(), SOCKET_CHARSET);
+    final Writer streamWriter = new OutputStreamWriter(socket.getOutputStream(), SOCKET_CHARSET);
+    final Reader streamReader = new InputStreamReader(socket.getInputStream(), SOCKET_CHARSET);
+
+    ConnectionLogger.LoggableReader loggableReader = new ConnectionLogger.LoggableReader() {
+      private final LineReader lineReader;
+      {
+        final BufferedReader bufferedReader =
+            new BufferedReader(streamReader, INPUT_BUFFER_SIZE_BYTES);
+        lineReader = new LineReader() {
+          public int read(char[] cbuf, int off, int len) throws IOException {
+            return bufferedReader.read(cbuf, off, len);
+          }
+          public String readLine() throws IOException {
+            return bufferedReader.readLine();
+          }
+        };
+      }
+
+      public LineReader getReader() {
+        return lineReader;
+      }
+
+      public void markSeparatorForLog() {
+      }
+    };
+
+    ConnectionLogger.LoggableWriter loggableWriter = new ConnectionLogger.LoggableWriter() {
+      private final BufferedWriter bufferedWriter = new BufferedWriter(streamWriter);
+      public Writer getWriter() {
+        return bufferedWriter;
+      }
+      public void markSeparatorForLog() {
+      }
+    };
 
     if (connectionLogger != null) {
-      streamWriter = connectionLogger.wrapWriter(streamWriter);
-      streamReader = connectionLogger.wrapReader(streamReader);
+      loggableWriter = connectionLogger.wrapWriter(loggableWriter);
+      loggableReader = connectionLogger.wrapReader(loggableReader);
       connectionLogger.setConnectionCloser(new ConnectionLogger.ConnectionCloser() {
         public void closeConnection() {
           close();
@@ -296,8 +335,8 @@
       });
     }
 
-    this.writer = new BufferedWriter(streamWriter);
-    this.reader = new BufferedReader(streamReader, INPUT_BUFFER_SIZE_BYTES);
+    this.writer = loggableWriter;
+    this.reader = loggableReader;
     isAttached.set(true);
 
     this.readerThread = new ReaderThread(reader, writer);
--- a/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/WorkspaceLineBreakpointAdapter.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/WorkspaceLineBreakpointAdapter.java	Wed Jan 27 15:59:22 2010 -0800
@@ -19,6 +19,7 @@
 package org.symbian.tools.wrttools.debug.internal;
 
 import org.chromium.debug.core.model.LineBreakpointAdapter;
+import org.chromium.debug.core.model.VProjectWorkspaceBridge;
 import org.eclipse.ui.IWorkbenchPart;
 import org.eclipse.ui.texteditor.ITextEditor;
 import org.eclipse.wst.jsdt.internal.ui.javaeditor.JavaEditor;
@@ -33,4 +34,9 @@
 			return null;
 		}
 	}
+
+    @Override
+    protected String getDebugModelId() {
+      return VProjectWorkspaceBridge.DEBUG_MODEL_ID;
+    }
 }
--- a/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/launch/DebugConnectionJob.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/launch/DebugConnectionJob.java	Wed Jan 27 15:59:22 2010 -0800
@@ -20,11 +20,13 @@
 
 import java.net.URI;
 
+import org.chromium.debug.core.model.DebugTargetImpl;
 import org.chromium.debug.core.model.Destructable;
 import org.chromium.debug.core.model.DestructingGuard;
 import org.chromium.debug.core.model.JavascriptVmEmbedder;
 import org.chromium.debug.core.model.JavascriptVmEmbedderFactory;
 import org.chromium.debug.core.model.NamedConnectionLoggerFactory;
+import org.chromium.debug.core.model.WorkspaceBridge;
 import org.chromium.debug.core.model.JavascriptVmEmbedder.ConnectionToRemote;
 import org.chromium.sdk.ConnectionLogger;
 import org.eclipse.core.resources.IProject;
@@ -32,7 +34,6 @@
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.debug.core.DebugPlugin;
 import org.eclipse.debug.core.ILaunch;
-import org.symbian.tools.wrttools.debug.internal.model.DebugTargetImpl;
 import org.symbian.tools.wrttools.previewer.http.IPreviewStartupListener;
 
 public class DebugConnectionJob implements IPreviewStartupListener {
@@ -45,7 +46,8 @@
 	private final ILaunch launch;
 	private final IProject project;
 
-	public DebugConnectionJob(IProject project, final int port, final ILaunch launch) {
+	public DebugConnectionJob(IProject project, final int port,
+			final ILaunch launch) {
 		this.project = project;
 		this.port = port;
 		this.launch = launch;
@@ -64,53 +66,47 @@
 
 	@Override
 	public boolean browserRunning(URI uri) throws CoreException {
-		final DebugTargetImpl target = new DebugTargetImpl(launch, project);
-		final JavascriptVmEmbedder.ConnectionToRemote remoteServer = createConnectionToRemote(
+		JavascriptVmEmbedder.ConnectionToRemote remoteServer = createConnectionToRemote(
 				port, launch, uri);
+		DestructingGuard destructingGuard = new DestructingGuard();
 		try {
-		
-			DestructingGuard destructingGuard = new DestructingGuard();
-			try {
-				Destructable lauchDestructor = new Destructable() {
-					public void destruct() {
-						if (!launch.hasChildren()) {
-							DebugPlugin.getDefault().getLaunchManager()
-									.removeLaunch(launch);
-						}
-					}
-				};
-		
-				destructingGuard.addValue(lauchDestructor);
-		
-				Destructable targetDestructor = new Destructable() {
-					public void destruct() {
-						terminateTarget(target);
+			Destructable lauchDestructor = new Destructable() {
+				public void destruct() {
+					if (!launch.hasChildren()) {
+						DebugPlugin.getDefault().getLaunchManager()
+								.removeLaunch(launch);
 					}
-				};
-				destructingGuard.addValue(targetDestructor);
-				boolean attached = target.attach(project.getName(), remoteServer,
-						destructingGuard, new Runnable() {
-							public void run() {
-								target.setupBreakpointsFromResources();
-							}
-						}, new NullProgressMonitor());
-				if (!attached) {
-					// Error
-					return false;
+				}
+			};
+
+			destructingGuard.addValue(lauchDestructor);
+
+			WorkspaceBridge.Factory bridgeFactory = new WRTProjectWorkspaceBridge.Factory(
+					project);
+
+			final DebugTargetImpl target = new DebugTargetImpl(launch,
+					bridgeFactory);
+
+			Destructable targetDestructor = new Destructable() {
+				public void destruct() {
+					terminateTarget(target);
 				}
-		
-				launch.setSourceLocator(target.getSourceLocator());
-		
-				launch.addDebugTarget(target);
-		
-				// All OK
-				destructingGuard.discharge();
-			} finally {
-				destructingGuard.doFinally();
+			};
+			destructingGuard.addValue(targetDestructor);
+
+			boolean attached = target.attach(remoteServer, destructingGuard,
+					null, new NullProgressMonitor());
+			if (!attached) {
+				// Error
+				return false;
 			}
-		
+
+			launch.addDebugTarget(target);
+
+			// All OK
+			destructingGuard.discharge();
 		} finally {
-			remoteServer.disposeConnection();
+			destructingGuard.doFinally();
 		}
 		return true;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/launch/WRTProjectWorkspaceBridge.java	Wed Jan 27 15:59:22 2010 -0800
@@ -0,0 +1,161 @@
+package org.symbian.tools.wrttools.debug.internal.launch;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.chromium.debug.core.model.ChromiumLineBreakpoint;
+import org.chromium.debug.core.model.DebugTargetImpl;
+import org.chromium.debug.core.model.StackFrame;
+import org.chromium.debug.core.model.VProjectWorkspaceBridge;
+import org.chromium.debug.core.model.WorkspaceBridge;
+import org.chromium.sdk.JavascriptVm;
+import org.chromium.sdk.Script;
+import org.chromium.sdk.JavascriptVm.ScriptsCallback;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.ISourceLocator;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.symbian.tools.wrttools.debug.internal.Activator;
+import org.symbian.tools.wrttools.debug.internal.model.ResourceManager;
+import org.symbian.tools.wrttools.debug.internal.model.WorkspaceBreakpointHandler;
+
+public class WRTProjectWorkspaceBridge implements WorkspaceBridge {
+	public static final class Factory implements WorkspaceBridge.Factory {
+		private final IProject project;
+
+		public Factory(IProject project) {
+			this.project = project;
+		}
+
+		@Override
+		public WorkspaceBridge attachedToVm(DebugTargetImpl debugTargetImpl,
+				JavascriptVm javascriptVm) {
+			return new WRTProjectWorkspaceBridge(debugTargetImpl, javascriptVm,
+					project);
+		}
+
+		@Override
+		public String getDebugModelIdentifier() {
+			return DEBUG_MODEL_ID;
+		}
+
+		@Override
+		public JsLabelProvider getLabelProvider() {
+			return new WrtLabelProvider();
+		}
+
+	}
+
+	public final static String DEBUG_MODEL_ID = VProjectWorkspaceBridge.DEBUG_MODEL_ID;
+
+	private final BreakpointHandler breakpointHandler;
+	private final JavascriptVm javascriptVm;
+	private final IProject project;
+	private final ResourceManager resourceManager;
+
+	public WRTProjectWorkspaceBridge(DebugTargetImpl debugTargetImpl,
+			JavascriptVm javascriptVm, IProject project) {
+		this.javascriptVm = javascriptVm;
+		this.project = project;
+		this.resourceManager = new ResourceManager();
+		breakpointHandler = new WorkspaceBreakpointHandler(debugTargetImpl,
+				javascriptVm, resourceManager);
+		ILaunch launch = debugTargetImpl.getLaunch();
+		launch.setSourceLocator(sourceLocator);
+	}
+
+	@Override
+	public void beforeDetach() {
+		// Do nothing
+	}
+
+	@Override
+	public BreakpointHandler getBreakpointHandler() {
+		return breakpointHandler;
+	}
+
+	@Override
+	public IFile getScriptResource(Script script) {
+		return resourceManager.getResource(script);
+	}
+
+	@Override
+	public void handleVmResetEvent() {
+		resourceManager.clear();
+	}
+
+	@Override
+	public void launchRemoved() {
+		// Do nothing
+	}
+
+	@Override
+	public void reloadScriptsAtStart() {
+		javascriptVm.getScripts(new ScriptsCallback() {
+			public void failure(String errorMessage) {
+				Activator.log(errorMessage);
+			}
+
+			public void success(Collection<Script> scripts) {
+				if (!javascriptVm.isAttached()) {
+					return;
+				}
+				for (Script script : scripts) {
+					resourceManager.addScript(script);
+				}
+
+				IMarker[] markers;
+				try {
+					markers = project.findMarkers(
+							ChromiumLineBreakpoint.BREAKPOINT_MARKER, true,
+							IResource.DEPTH_INFINITE);
+					Collection<ChromiumLineBreakpoint> breakpoints = new ArrayList<ChromiumLineBreakpoint>(
+							markers.length);
+					for (IMarker marker : markers) {
+						// If it is not ChromiumLineBreakpoint -
+						// something's gone horribly wrong. Better get
+						// ClassCastException
+						ChromiumLineBreakpoint breakpoint = (ChromiumLineBreakpoint) DebugPlugin
+								.getDefault().getBreakpointManager()
+								.getBreakpoint(marker);
+						breakpointHandler.breakpointAdded(breakpoint);
+						breakpoints.add(breakpoint);
+					}
+				} catch (CoreException e) {
+					Activator.log(e);
+				}
+
+			}
+		});
+	}
+
+	@Override
+	public void scriptLoaded(Script newScript) {
+		resourceManager.addScript(newScript);
+	}
+
+	/**
+	 * This very simple source locator works because we provide our own source
+	 * files. We'll have to try harder, once we link with resource js files.
+	 */
+	private final ISourceLocator sourceLocator = new ISourceLocator() {
+		public Object getSourceElement(IStackFrame stackFrame) {
+			if (stackFrame instanceof StackFrame == false) {
+				return null;
+			}
+			StackFrame jsStackFrame = (StackFrame) stackFrame;
+
+			Script script = jsStackFrame.getCallFrame().getScript();
+			if (script == null) {
+				return null;
+			}
+
+			return resourceManager.getResource(script);
+		}
+	};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/launch/WrtLabelProvider.java	Wed Jan 27 15:59:22 2010 -0800
@@ -0,0 +1,47 @@
+package org.symbian.tools.wrttools.debug.internal.launch;
+
+import org.chromium.debug.core.model.DebugTargetImpl;
+import org.chromium.debug.core.model.JavascriptThread;
+import org.chromium.debug.core.model.StackFrame;
+import org.chromium.debug.core.model.WorkspaceBridge.JsLabelProvider;
+import org.chromium.sdk.CallFrame;
+import org.chromium.sdk.Script;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.osgi.util.NLS;
+
+public class WrtLabelProvider implements JsLabelProvider {
+
+	@Override
+	public String getStackFrameLabel(StackFrame stackFrame)
+			throws DebugException {
+		CallFrame callFrame = stackFrame.getCallFrame();
+		String name = callFrame.getFunctionName();
+		Script script = callFrame.getScript();
+		if (script == null) {
+			return "<unknown>";
+		}
+		IFile resource = stackFrame.getDebugTarget().getScriptResource(script);
+		int line = script.getStartLine() + stackFrame.getLineNumber();
+		if (line != -1) {
+			String resourcePath = resource != null ? resource
+					.getProjectRelativePath().toString() : script.getName();
+			name = NLS.bind("{0} [{1}:{2}]", new Object[] { name, resourcePath,
+					line });
+		}
+		return name;
+	}
+
+	@Override
+	public String getTargetLabel(DebugTargetImpl debugTarget)
+			throws DebugException {
+		return "WRT Runtime";
+	}
+
+	@Override
+	public String getThreadLabel(JavascriptThread thread) throws DebugException {
+		return NLS.bind("JavaScript Thread ({0})",
+				(thread.isSuspended() ? "Suspended" : "Running")); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+}
--- a/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/model/DebugTargetImpl.java	Wed Jan 27 15:47:03 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,674 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.symbian.tools.wrttools.debug.internal.model;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-
-import org.chromium.debug.core.ChromiumDebugPlugin;
-import org.chromium.debug.core.model.ChromiumLineBreakpoint;
-import org.chromium.debug.core.model.DebugElementImpl;
-import org.chromium.debug.core.model.Destructable;
-import org.chromium.debug.core.model.DestructingGuard;
-import org.chromium.debug.core.model.IChromiumDebugTarget;
-import org.chromium.debug.core.model.IResourceManager;
-import org.chromium.debug.core.model.JavascriptVmEmbedder;
-import org.chromium.sdk.Breakpoint;
-import org.chromium.sdk.CallFrame;
-import org.chromium.sdk.DebugContext;
-import org.chromium.sdk.DebugEventListener;
-import org.chromium.sdk.ExceptionData;
-import org.chromium.sdk.JavascriptVm;
-import org.chromium.sdk.Script;
-import org.chromium.sdk.DebugContext.State;
-import org.chromium.sdk.DebugContext.StepAction;
-import org.chromium.sdk.JavascriptVm.BreakpointCallback;
-import org.chromium.sdk.JavascriptVm.ScriptsCallback;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IMarker;
-import org.eclipse.core.resources.IMarkerDelta;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.debug.core.DebugEvent;
-import org.eclipse.debug.core.DebugException;
-import org.eclipse.debug.core.DebugPlugin;
-import org.eclipse.debug.core.ILaunch;
-import org.eclipse.debug.core.ILaunchListener;
-import org.eclipse.debug.core.model.IBreakpoint;
-import org.eclipse.debug.core.model.IMemoryBlock;
-import org.eclipse.debug.core.model.IProcess;
-import org.eclipse.debug.core.model.ISourceLocator;
-import org.eclipse.debug.core.model.IStackFrame;
-import org.eclipse.debug.core.model.IThread;
-import org.symbian.tools.wrttools.debug.internal.Activator;
-
-/**
- * An IDebugTarget implementation for remote JavaScript debugging. Can debug any
- * target that supports the ChromeDevTools protocol.
- * 
- * Symbian branch is based on Revision 290
- */
-public class DebugTargetImpl extends DebugElementImpl implements IChromiumDebugTarget {
-
-	private static final IThread[] EMPTY_THREADS = new IThread[0];
-
-	private static final long OPERATION_TIMEOUT_MS = 15000L;
-
-	private final ILaunch launch;
-
-	private final JavascriptThread[] threads;
-
-	private JavascriptVmEmbedder vmEmbedder = STUB_VM_EMBEDDER;
-
-	private ResourceManager resourceManager;
-
-	private DebugContext debugContext;
-
-	private boolean isSuspended = false;
-
-	private boolean isDisconnected = false;
-
-	private final IProject debugProject;
-
-	public DebugTargetImpl(ILaunch launch, IProject project) {
-		super(null);
-		this.launch = launch;
-		this.debugProject = project;
-		this.threads = new JavascriptThread[] { new JavascriptThread(this) };
-	}
-
-	/**
-	 * Loads browser tabs, consults the {@code selector} which of the tabs to
-	 * attach to, and if any has been selected, requests an attachment to the
-	 * tab.
-	 * 
-	 * @param projectNameBase
-	 *            to create for the browser scripts
-	 * @param remoteServer
-	 *            embedding application we are connected with
-	 * @param attachCallback
-	 *            to invoke on successful attachment
-	 * @param monitor
-	 *            to report the progress to
-	 * @return whether the target has attached to a tab
-	 * @throws CoreException
-	 */
-	public boolean attach(String projectNameBase,
-			JavascriptVmEmbedder.ConnectionToRemote remoteServer,
-			DestructingGuard destructingGuard, Runnable attachCallback,
-			IProgressMonitor monitor) throws CoreException {
-		monitor.beginTask("", 2); //$NON-NLS-1$
-		JavascriptVmEmbedder.VmConnector connector = remoteServer.selectVm();
-		if (connector == null) {
-			return false;
-		}
-		monitor.worked(1);
-		return performAttach(projectNameBase, connector, destructingGuard,
-				attachCallback);
-	}
-
-	private boolean performAttach(String projectNameBase,
-			JavascriptVmEmbedder.VmConnector connector,
-			DestructingGuard destructingGuard, Runnable attachCallback)
-			throws CoreException {
-		final JavascriptVmEmbedder embedder = connector.attach(
-				embedderListener, debugEventListener);
-
-		Destructable embedderDestructor = new Destructable() {
-			public void destruct() {
-				embedder.getJavascriptVm().detach();
-			}
-		};
-
-		destructingGuard.addValue(embedderDestructor);
-
-		vmEmbedder = embedder;
-
-		// We might want to add some url-specific suffix here
-		String projectName = projectNameBase;
-		// We'd like to know when launch is removed to remove our project.
-		DebugPlugin.getDefault().getLaunchManager().addLaunchListener(
-				launchListener);
-		this.resourceManager = createResourceManager();
-		onAttach(projectName, attachCallback);
-		return true;
-	}
-
-	protected ResourceManager createResourceManager() {
-		return new ResourceManager();
-	}
-
-	private void onAttach(String projectName, Runnable attachCallback) {
-		DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(
-				this);
-		reloadScriptsAndPossiblyResume(attachCallback);
-	}
-
-	public void setupBreakpointsFromResources() {
-		try {
-			IMarker[] markers = debugProject.findMarkers(ChromiumLineBreakpoint.BREAKPOINT_MARKER, true, IResource.DEPTH_INFINITE);
-			Collection<ChromiumLineBreakpoint> breakpoints = new ArrayList<ChromiumLineBreakpoint>(markers.length);
-			for (IMarker marker : markers) {
-				// If it is not ChromiumLineBreakpoint -
-				// something's gone horribly wrong. Better get
-				// ClassCastException
-				ChromiumLineBreakpoint breakpoint = (ChromiumLineBreakpoint) DebugPlugin
-						.getDefault().getBreakpointManager().getBreakpoint(
-								marker);
-				registerBreakpoint(breakpoint, resourceManager
-						.translateResourceToScript(marker.getResource()));
-				breakpoints.add(breakpoint);
-			}
-		} catch (CoreException e) {
-			Activator.log(e);
-		}
-	}
-
-	private void reloadScriptsAndPossiblyResume(final Runnable attachCallback) {
-		reloadScripts(true, new Runnable() {
-			public void run() {
-				try {
-					if (attachCallback != null) {
-						attachCallback.run();
-					}
-				} finally {
-					fireCreationEvent();
-				}
-				Job job = new Job("Update debugger state") {
-					@Override
-					protected IStatus run(IProgressMonitor monitor) {
-						debugEventListener.resumedByDefault();
-						return Status.OK_STATUS;
-					}
-				};
-				job.schedule();
-			}
-		});
-	}
-
-	private void reloadScripts(boolean isSync, final Runnable runnable) {
-		Runnable command = new Runnable() {
-			public void run() {
-				vmEmbedder.getJavascriptVm().getScripts(new ScriptsCallback() {
-					public void failure(String errorMessage) {
-						Activator.log(errorMessage);
-					}
-
-					public void success(Collection<Script> scripts) {
-						if (!vmEmbedder.getJavascriptVm().isAttached()) {
-							return;
-						}
-						for (Script script : scripts) {
-							getResourceManager().addScript(script);
-						}
-						if (runnable != null) {
-							runnable.run();
-						}
-					}
-
-				});
-			}
-		};
-		if (isSync) {
-			command.run();
-			return;
-		}
-		Thread t = new Thread(command);
-		t.setDaemon(true);
-		t.start();
-		try {
-			t.join(OPERATION_TIMEOUT_MS);
-		} catch (InterruptedException e) {
-			Activator.log(e);
-		}
-	}
-
-	public String getName() throws DebugException {
-		return "WRT Runtime";
-	}
-
-	public IProcess getProcess() {
-		return null;
-	}
-
-	public JavascriptVmEmbedder getJavascriptEmbedder() {
-		return vmEmbedder;
-	}
-
-	public IThread[] getThreads() throws DebugException {
-		return isDisconnected() ? EMPTY_THREADS : threads;
-	}
-
-	public boolean hasThreads() throws DebugException {
-		return getThreads().length > 0;
-	}
-
-	public boolean supportsBreakpoint(IBreakpoint breakpoint) {
-		return ChromiumDebugPlugin.DEBUG_MODEL_ID.equals(breakpoint
-				.getModelIdentifier())
-				&& !isDisconnected();
-	}
-
-	@Override
-	public DebugTargetImpl getDebugTarget() {
-		return this;
-	}
-
-	@Override
-	public ILaunch getLaunch() {
-		return launch;
-	}
-
-	@Override
-	public String getModelIdentifier() {
-		return ChromiumDebugPlugin.DEBUG_MODEL_ID;
-	}
-
-	public boolean canTerminate() {
-		return !isTerminated();
-	}
-
-	public boolean isTerminated() {
-		return isDisconnected();
-	}
-
-	public void terminate() throws DebugException {
-		disconnect();
-	}
-
-	public boolean canResume() {
-		return !isDisconnected() && isSuspended();
-	}
-
-	public synchronized boolean isSuspended() {
-		return isSuspended;
-	}
-
-	private synchronized void setSuspended(boolean isSuspended) {
-		this.isSuspended = isSuspended;
-	}
-
-	public void suspended(int detail) {
-		setSuspended(true);
-		getThread().reset();
-		fireSuspendEvent(detail);
-	}
-
-	public void resume() throws DebugException {
-		debugContext.continueVm(StepAction.CONTINUE, 1, null);
-		// Let's pretend Chromium does respond to the "continue" request
-		// immediately
-		resumed(DebugEvent.CLIENT_REQUEST);
-	}
-
-	public void resumed(int detail) {
-		fireResumeEvent(detail);
-	}
-
-	public boolean canSuspend() {
-		return !isDisconnected() && !isSuspended();
-	}
-
-	public void suspend() throws DebugException {
-		vmEmbedder.getJavascriptVm().suspend(null);
-	}
-
-	public boolean canDisconnect() {
-		return !isDisconnected();
-	}
-
-	public void disconnect() throws DebugException {
-		if (!canDisconnect()) {
-			return;
-		}
-		if (!vmEmbedder.getJavascriptVm().detach()) {
-			Activator
-					.log("Received bad result from browser while disconnecting");
-		}
-		// This is a duplicated call to disconnected().
-		// The primary one comes from V8DebuggerToolHandler#onDebuggerDetached
-		// but we want to make sure the target becomes disconnected even if
-		// there is a browser failure and it does not respond.
-		debugEventListener.disconnected();
-	}
-
-	public synchronized boolean isDisconnected() {
-		return isDisconnected;
-	}
-
-	public IMemoryBlock getMemoryBlock(long startAddress, long length)
-			throws DebugException {
-		return null;
-	}
-
-	public boolean supportsStorageRetrieval() {
-		return false;
-	}
-
-	public IProject getDebugProject() {
-		return debugProject;
-	}
-
-	/**
-	 * Fires a debug event
-	 * 
-	 * @param event
-	 *            to be fired
-	 */
-	public void fireEvent(DebugEvent event) {
-		DebugPlugin debugPlugin = DebugPlugin.getDefault();
-		if (debugPlugin != null) {
-			debugPlugin.fireDebugEventSet(new DebugEvent[] { event });
-		}
-	}
-
-	public void fireEventForThread(int kind, int detail) {
-		try {
-			IThread[] threads = getThreads();
-			if (threads.length > 0) {
-				fireEvent(new DebugEvent(threads[0], kind, detail));
-			}
-		} catch (DebugException e) {
-			// Actually, this is not thrown in our getThreads()
-			return;
-		}
-	}
-
-	public void fireCreationEvent() {
-		setDisconnected(false);
-		fireEventForThread(DebugEvent.CREATE, DebugEvent.UNSPECIFIED);
-	}
-
-	public synchronized void setDisconnected(boolean disconnected) {
-		isDisconnected = disconnected;
-	}
-
-	public void fireResumeEvent(int detail) {
-		setSuspended(false);
-		fireEventForThread(DebugEvent.RESUME, detail);
-		fireEvent(new DebugEvent(this, DebugEvent.RESUME, detail));
-	}
-
-	public void fireSuspendEvent(int detail) {
-		setSuspended(true);
-		fireEventForThread(DebugEvent.SUSPEND, detail);
-		fireEvent(new DebugEvent(this, DebugEvent.SUSPEND, detail));
-	}
-
-	public void fireTerminateEvent() {
-		// TODO(peter.rybin): from Alexander Pavlov: I think you need to fire a
-		// terminate event after
-		// this line, for consolePseudoProcess if one is not null.
-		fireEventForThread(DebugEvent.TERMINATE, DebugEvent.UNSPECIFIED);
-		fireEvent(new DebugEvent(this, DebugEvent.TERMINATE,
-				DebugEvent.UNSPECIFIED));
-		fireEvent(new DebugEvent(getLaunch(), DebugEvent.TERMINATE,
-				DebugEvent.UNSPECIFIED));
-	}
-
-	public void breakpointAdded(IBreakpoint breakpoint) {
-		if (!supportsBreakpoint(breakpoint)) {
-			return;
-		}
-		try {
-			if (breakpoint.isEnabled()) {
-				// Class cast is ensured by the supportsBreakpoint
-				// implementation
-				final ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
-				IFile file = (IFile) breakpoint.getMarker().getResource();
-				if (!getResourceManager().isAddingFile(file)) {
-					final Script script = getResourceManager().getScript(file);
-					if (script != null) {
-						registerBreakpoint(lineBreakpoint, script.getName());
-					}
-				}
-			}
-		} catch (CoreException e) {
-			Activator.log(e);
-		}
-	}
-
-	public void registerBreakpoint(final ChromiumLineBreakpoint breakpoint,
-			final String script) throws CoreException {
-		final int line = (breakpoint.getLineNumber() - 1);
-		BreakpointCallback callback = new BreakpointCallback() {
-			public void success(Breakpoint b) {
-				breakpoint.setBreakpoint(b);
-			}
-
-			public void failure(String errorMessage) {
-				Activator.log(errorMessage);
-			}
-		};
-		// ILineBreakpoint lines are 1-based while V8 lines are 0-based
-		JavascriptVm javascriptVm = vmEmbedder.getJavascriptVm();
-		if (script != null) {
-			javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_NAME, script
-					,line, Breakpoint.EMPTY_VALUE, breakpoint
-					.isEnabled(), breakpoint.getCondition(), breakpoint
-					.getIgnoreCount(), callback);
-		} else {
-			javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_ID, String
-					.valueOf(script), line, Breakpoint.EMPTY_VALUE,
-					breakpoint.isEnabled(), breakpoint.getCondition(),
-					breakpoint.getIgnoreCount(), callback);
-		}
-	}
-
-	public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
-		if (!supportsBreakpoint(breakpoint)) {
-			return;
-		}
-		// Class cast is ensured by the supportsBreakpoint implementation
-		((ChromiumLineBreakpoint) breakpoint).changed();
-	}
-
-	public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
-		if (!supportsBreakpoint(breakpoint)) {
-			return;
-		}
-		try {
-			if (breakpoint.isEnabled()) {
-				// Class cast is ensured by the supportsBreakpoint
-				// implementation
-				ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
-				lineBreakpoint.clear();
-			}
-		} catch (CoreException e) {
-			Activator.log(e);
-		}
-	}
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public Object getAdapter(Class adapter) {
-		if (ILaunch.class.equals(adapter)) {
-			return this.launch;
-		}
-		return super.getAdapter(adapter);
-	}
-
-	public IResourceManager getResourceManager() {
-		return resourceManager;
-	}
-
-	public JavascriptThread getThread() {
-		return isDisconnected() ? null : threads[0];
-	}
-
-	private static void breakpointsHit(
-			Collection<? extends Breakpoint> breakpointsHit) {
-		if (breakpointsHit.isEmpty()) {
-			return;
-		}
-		IBreakpoint[] breakpoints = DebugPlugin.getDefault()
-				.getBreakpointManager().getBreakpoints(
-						ChromiumDebugPlugin.DEBUG_MODEL_ID);
-		for (IBreakpoint breakpoint : breakpoints) {
-			ChromiumLineBreakpoint jsBreakpoint = (ChromiumLineBreakpoint) breakpoint;
-			if (breakpointsHit.contains(jsBreakpoint.getBrowserBreakpoint())) {
-				jsBreakpoint.setIgnoreCount(-1); // reset ignore count as we've
-													// hit it
-			}
-		}
-	}
-
-	private static String trim(String text, int maxLength) {
-		if (text == null || text.length() <= maxLength) {
-			return text;
-		}
-		return text.substring(0, maxLength - 3) + "..."; //$NON-NLS-1$
-	}
-
-	public DebugContext getDebugContext() {
-		return debugContext;
-	}
-
-	public ISourceLocator getSourceLocator() {
-		return sourceLocator;
-	}
-
-	private final DebugEventListenerImpl debugEventListener = new DebugEventListenerImpl();
-
-	class DebugEventListenerImpl implements DebugEventListener {
-		// Synchronizes calls from ReaderThread of Connection and one call from
-		// some worker thread
-		private final Object suspendResumeMonitor = new Object();
-		private boolean alreadyResumedOrSuspended = false;
-
-		public void disconnected() {
-			if (!isDisconnected()) {
-				setDisconnected(true);
-				DebugPlugin.getDefault().getBreakpointManager()
-						.removeBreakpointListener(DebugTargetImpl.this);
-				fireTerminateEvent();
-			}
-		}
-
-		public void resumedByDefault() {
-			synchronized (suspendResumeMonitor) {
-				if (!alreadyResumedOrSuspended) {
-					resumed();
-				}
-			}
-		}
-
-		public void resumed() {
-			synchronized (suspendResumeMonitor) {
-				DebugTargetImpl.this.resumed(DebugEvent.CLIENT_REQUEST);
-				alreadyResumedOrSuspended = true;
-			}
-		}
-
-		public void scriptLoaded(Script newScript) {
-			getResourceManager().addScript(newScript);
-		}
-
-		public void suspended(DebugContext context) {
-			synchronized (suspendResumeMonitor) {
-				DebugTargetImpl.this.debugContext = context;
-				breakpointsHit(context.getBreakpointsHit());
-				int suspendedDetail;
-				if (context.getState() == State.EXCEPTION) {
-					logExceptionFromContext(context);
-					suspendedDetail = DebugEvent.BREAKPOINT;
-				} else {
-					if (context.getBreakpointsHit().isEmpty()) {
-						suspendedDetail = DebugEvent.STEP_END;
-					} else {
-						suspendedDetail = DebugEvent.BREAKPOINT;
-					}
-				}
-				DebugTargetImpl.this.suspended(suspendedDetail);
-
-				alreadyResumedOrSuspended = true;
-			}
-		}
-	}
-
-	private void logExceptionFromContext(DebugContext context) {
-		ExceptionData exceptionData = context.getExceptionData();
-		CallFrame topFrame = context.getCallFrames().get(0);
-		Script script = topFrame.getScript();
-		Activator.log(MessageFormat.format("{0} {1} (in {2}:{3}): {4}", exceptionData
-				.isUncaught() ? "Uncaught" : "Caught", exceptionData
-				.getExceptionMessage(), script != null ? script.getName()
-				: "<unknown>", //$NON-NLS-1$
-				topFrame.getLineNumber(), trim(exceptionData.getSourceText(),
-						80)));
-	}
-
-	private final JavascriptVmEmbedder.Listener embedderListener = new JavascriptVmEmbedder.Listener() {
-		public void reset() {
-			getResourceManager().clear();
-			fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.STATE));
-		}
-
-		public void closed() {
-			fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.STATE));
-		}
-	};
-
-	private final ILaunchListener launchListener = new ILaunchListener() {
-		public void launchAdded(ILaunch launch) {
-		}
-
-		public void launchChanged(ILaunch launch) {
-		}
-
-		// TODO(peter.rybin): maybe have one instance of listener for all
-		// targets?
-		public void launchRemoved(ILaunch launch) {
-			if (launch != DebugTargetImpl.this.launch) {
-				return;
-			}
-			DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(
-					this);
-		}
-	};
-
-	private final static JavascriptVmEmbedder STUB_VM_EMBEDDER = new JavascriptVmEmbedder() {
-		public JavascriptVm getJavascriptVm() {
-			// TODO(peter.rybin): decide and redo this exception
-			throw new UnsupportedOperationException();
-		}
-
-		public String getTargetName() {
-			// TODO(peter.rybin): decide and redo this exception
-			throw new UnsupportedOperationException();
-		}
-
-		public String getThreadName() {
-			// TODO(peter.rybin): decide and redo this exception
-			throw new UnsupportedOperationException();
-		}
-	};
-
-	/**
-	 * This very simple source locator works because we provide our own source
-	 * files. We'll have to try harder, once we link with resource js files.
-	 */
-	private final ISourceLocator sourceLocator = new ISourceLocator() {
-		public Object getSourceElement(IStackFrame stackFrame) {
-			if (stackFrame instanceof StackFrame == false) {
-				return null;
-			}
-			StackFrame jsStackFrame = (StackFrame) stackFrame;
-
-			Script script = jsStackFrame.getCallFrame().getScript();
-			if (script == null) {
-				return null;
-			}
-
-			return resourceManager.getResource(script);
-		}
-	};
-}
--- a/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/model/JavascriptThread.java	Wed Jan 27 15:47:03 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.symbian.tools.wrttools.debug.internal.model;
-
-import java.util.List;
-
-import org.chromium.sdk.CallFrame;
-import org.eclipse.debug.core.DebugException;
-import org.eclipse.osgi.util.NLS;
-
-/**
- * This class represents the only Chromium V8 VM thread.
- * 
- * Symbian branch is based on revision 234
- */
-public class JavascriptThread extends
-		org.chromium.debug.core.model.JavascriptThread {
-
-	private static final StackFrame[] EMPTY_FRAMES = new StackFrame[0];
-
-	/**
-	 * Cached stack
-	 */
-	private StackFrame[] stackFrames;
-
-	/**
-	 * Constructs a new thread for the given target
-	 * 
-	 * @param debugTarget
-	 *            this thread is created for
-	 */
-	public JavascriptThread(DebugTargetImpl debugTarget) {
-		super(debugTarget);
-	}
-
-	public org.chromium.debug.core.model.StackFrame[] getStackFrames()
-			throws DebugException {
-		if (isSuspended()) {
-			ensureStackFrames();
-			return stackFrames;
-		} else {
-			return EMPTY_FRAMES;
-		}
-	}
-
-	public void reset() {
-		this.stackFrames = null;
-	}
-
-	private void ensureStackFrames() {
-		this.stackFrames = wrapStackFrames(getDebugTarget().getDebugContext()
-				.getCallFrames());
-	}
-
-	private StackFrame[] wrapStackFrames(List<? extends CallFrame> jsFrames) {
-		StackFrame[] frames = new StackFrame[jsFrames.size()];
-		for (int i = 0, size = frames.length; i < size; ++i) {
-			frames[i] = new StackFrame(getDebugTarget(), this, jsFrames.get(i));
-		}
-		return frames;
-	}
-
-	public String getName() throws DebugException {
-		return NLS.bind("JavaScript Thread ({0})",
-				(isSuspended() ? "Suspended" : "Running")); //$NON-NLS-1$ //$NON-NLS-2$
-	}
-}
--- a/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/model/ResourceManager.java	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/model/ResourceManager.java	Wed Jan 27 15:59:22 2010 -0800
@@ -7,7 +7,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.chromium.debug.core.model.IResourceManager;
 import org.chromium.sdk.Script;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IResource;
@@ -19,7 +18,7 @@
  * 
  * Symbian branch is currently based on Revision 138
  */
-public class ResourceManager implements IResourceManager {
+public class ResourceManager {
 	/**
 	 * Script identifier for a breakpoint location.
 	 */
--- a/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/model/StackFrame.java	Wed Jan 27 15:47:03 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.symbian.tools.wrttools.debug.internal.model;
-
-import org.chromium.debug.core.model.IChromiumDebugTarget;
-import org.chromium.sdk.CallFrame;
-import org.chromium.sdk.Script;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.debug.core.DebugException;
-import org.eclipse.osgi.util.NLS;
-
-/**
- * An IStackFrame implementation over a JsStackFrame instance.
- * 
- * Symbian branch is based on revision 261
- */
-public class StackFrame extends org.chromium.debug.core.model.StackFrame {
-	private final CallFrame stackFrame;
-
-	/**
-	 * Constructs a stack frame for the given handler using the FrameMirror data
-	 * from the remote V8 VM.
-	 * 
-	 * @param debugTarget
-	 *            the global parent
-	 * @param thread
-	 *            for which the stack frame is created
-	 * @param stackFrame
-	 *            an underlying SDK stack frame
-	 */
-	public StackFrame(IChromiumDebugTarget debugTarget,
-			JavascriptThread thread, CallFrame stackFrame) {
-		super(debugTarget, thread, stackFrame);
-		this.stackFrame = stackFrame;
-	}
-
-	public String getName() throws DebugException {
-		String name = stackFrame.getFunctionName();
-		Script script = stackFrame.getScript();
-		if (script == null) {
-			return "<unknown>";
-		}
-		IFile resource = getDebugTarget().getResourceManager().getResource(
-				script);
-		int line = script.getStartLine() + getLineNumber();
-		if (line != -1) {
-			String resourcePath = resource != null ? resource.getProjectRelativePath().toString() : script.getName();
-			name = NLS.bind("{0} [{1}:{2}]", new Object[] { name,
-					resourcePath, line });
-		}
-		return name;
-	}
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.symbian.tools.wrttools.debug.core/src/org/symbian/tools/wrttools/debug/internal/model/WorkspaceBreakpointHandler.java	Wed Jan 27 15:59:22 2010 -0800
@@ -0,0 +1,128 @@
+/**
+ * 
+ */
+package org.symbian.tools.wrttools.debug.internal.model;
+
+import java.util.Collection;
+
+import org.chromium.debug.core.ChromiumDebugPlugin;
+import org.chromium.debug.core.model.ChromiumLineBreakpoint;
+import org.chromium.debug.core.model.DebugTargetImpl;
+import org.chromium.debug.core.model.WorkspaceBridge.BreakpointHandler;
+import org.chromium.sdk.Breakpoint;
+import org.chromium.sdk.JavascriptVm;
+import org.chromium.sdk.JavascriptVm.BreakpointCallback;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.symbian.tools.wrttools.debug.internal.Activator;
+import org.symbian.tools.wrttools.debug.internal.launch.WRTProjectWorkspaceBridge;
+
+public final class WorkspaceBreakpointHandler implements BreakpointHandler {
+	private final ResourceManager resourceManager;
+	private final DebugTargetImpl debugTarget;
+	private final JavascriptVm vm;
+
+	public WorkspaceBreakpointHandler(DebugTargetImpl debugTarget, JavascriptVm vm, ResourceManager resourceManager) {
+		this.debugTarget = debugTarget;
+		this.vm = vm;
+		this.resourceManager = resourceManager;
+	}
+	
+	public boolean supportsBreakpoint(IBreakpoint breakpoint) {
+		return WRTProjectWorkspaceBridge.DEBUG_MODEL_ID.equals(breakpoint.getModelIdentifier())
+				&& !debugTarget.isDisconnected();
+	}
+
+	public void registerBreakpoint(final ChromiumLineBreakpoint breakpoint,
+			final String script) throws CoreException {
+		final int line = (breakpoint.getLineNumber() - 1);
+		BreakpointCallback callback = new BreakpointCallback() {
+			public void success(Breakpoint b) {
+				breakpoint.setBreakpoint(b);
+			}
+
+			public void failure(String errorMessage) {
+				Activator.log(errorMessage);
+			}
+		};
+		// ILineBreakpoint lines are 1-based while V8 lines are 0-based
+		JavascriptVm javascriptVm = vm;
+		if (script != null) {
+			javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_NAME, script
+					,line, Breakpoint.EMPTY_VALUE, breakpoint
+					.isEnabled(), breakpoint.getCondition(), breakpoint
+					.getIgnoreCount(), callback);
+		} else {
+			javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_ID, String
+					.valueOf(script), line, Breakpoint.EMPTY_VALUE,
+					breakpoint.isEnabled(), breakpoint.getCondition(),
+					breakpoint.getIgnoreCount(), callback);
+		}
+	}
+
+	public void breakpointAdded(IBreakpoint breakpoint) {
+		if (!supportsBreakpoint(breakpoint)) {
+			return;
+		}
+		try {
+			if (breakpoint.isEnabled()) {
+				// Class cast is ensured by the supportsBreakpoint
+				// implementation
+				final ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
+				IFile file = (IFile) breakpoint.getMarker().getResource();
+				if (!resourceManager.isAddingFile(file)) {
+					final String script = resourceManager.translateResourceToScript(file);
+					if (script != null) {
+						registerBreakpoint(lineBreakpoint, script);
+					}
+				}
+			}
+		} catch (CoreException e) {
+			Activator.log(e);
+		}
+	}
+
+	public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
+		if (!supportsBreakpoint(breakpoint)) {
+			return;
+		}
+		// Class cast is ensured by the supportsBreakpoint implementation
+		((ChromiumLineBreakpoint) breakpoint).changed();
+	}
+
+	public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
+		if (!supportsBreakpoint(breakpoint)) {
+			return;
+		}
+		try {
+			if (breakpoint.isEnabled()) {
+				// Class cast is ensured by the supportsBreakpoint
+				// implementation
+				ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
+				lineBreakpoint.clear();
+			}
+		} catch (CoreException e) {
+			ChromiumDebugPlugin.log(e);
+		}
+	}
+
+	public void breakpointsHit(
+			Collection<? extends Breakpoint> breakpointsHit) {
+		if (breakpointsHit.isEmpty()) {
+			return;
+		}
+		IBreakpoint[] breakpoints = DebugPlugin.getDefault()
+				.getBreakpointManager().getBreakpoints(WRTProjectWorkspaceBridge.DEBUG_MODEL_ID);
+		for (IBreakpoint breakpoint : breakpoints) {
+			ChromiumLineBreakpoint jsBreakpoint = (ChromiumLineBreakpoint) breakpoint;
+			if (breakpointsHit
+					.contains(jsBreakpoint.getBrowserBreakpoint())) {
+				jsBreakpoint.setIgnoreCount(-1); // reset ignore count as
+													// we've hit it
+			}
+		}
+	}
+}
\ No newline at end of file
--- a/org.symbian.tools.wrttools.product/launch/WRT IDE (Product).launch	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.symbian.tools.wrttools.product/launch/WRT IDE (Product).launch	Wed Jan 27 15:59:22 2010 -0800
@@ -21,8 +21,8 @@
 <stringAttribute key="product" value="org.symbian.tools.wrttools.product.product"/>
 <stringAttribute key="productFile" value="\org.symbian.tools.wrttools.product\wrt-ide.product"/>
 <booleanAttribute key="restart" value="false"/>
-<stringAttribute key="selected_target_plugins" value="org.eclipse.wst.jsdt.manipulation@default:default,org.eclipse.equinox.p2.publisher@default:default,org.apache.xerces@default:default,org.apache.commons.logging@default:default,org.eclipse.ecf.filetransfer@default:default,org.eclipse.ui@default:default,org.eclipse.wst.validation.infopop@default:default,org.eclipse.wst.validation.ui@default:default,org.eclipse.equinox.p2.ui@default:default,org.mozilla.xpcom@default:default,org.eclipse.equinox.p2.updatechecker@default:default,org.eclipse.wst.command.env.core@default:default,org.eclipse.wst.doc.user@default:default,org.eclipse.wst.html.ui.infopop@default:default,org.eclipse.equinox.launcher.gtk.linux.x86@default:false,org.apache.oro@default:default,org.eclipse.swt.gtk.linux.x86@default:false,org.eclipse.emf.mapping.ecore2ecore@default:default,org.eclipse.wst.internet.monitor.core@default:default,org.eclipse.equinox.p2.core@default:default,org.eclipse.update.ui@default:default,org.eclipse.wst.common.snippets@default:default,org.eclipse.ui.navigator@default:default,org.eclipse.emf.ecore.change.edit@default:default,org.eclipse.equinox.p2.garbagecollector@default:default,org.eclipse.emf.edit.ui@default:default,org.eclipse.ltk.core.refactoring@default:default,org.eclipse.debug.ui@default:default,org.eclipse.compare@default:default,org.eclipse.platform@default:default,org.eclipse.ecf.provider.filetransfer.ssl@default:false,org.eclipse.equinox.launcher.win32.win32.x86@default:false,org.eclipse.equinox.registry@default:default,org.eclipse.update.core@default:default,org.eclipse.emf.mapping.ecore.editor@default:default,org.eclipse.wst.common.uriresolver@default:default,org.eclipse.draw2d@default:default,org.eclipse.equinox.p2.ui.sdk.scheduler@default:default,org.apache.axis@default:default,org.eclipse.core.runtime@default:true,net.sourceforge.lpg.lpgjavaruntime@default:default,org.eclipse.team.core@default:default,org.eclipse.core.boot@default:default,org.eclipse.core.variables@default:default,org.eclipse.core.runtime.compatibility@default:default,org.eclipse.emf.databinding.edit@default:default,org.eclipse.ui.browser@default:default,org.eclipse.wst.jsdt.core@default:default,org.apache.velocity@default:default,org.eclipse.equinox.p2.metadata.repository@default:default,org.eclipse.wst.xmleditor.doc.user@default:default,org.eclipse.core.jobs@default:default,org.eclipse.ui.views@default:default,org.eclipse.compare.core@default:default,org.eclipse.wtp.epp.package.jee.intro@default:default,org.eclipse.equinox.p2.repository@default:default,javax.servlet.jsp@default:default,org.mozilla.xulrunner.win32.win32.x86@default:false,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.mapping@default:default,org.eclipse.equinox.p2.touchpoint.eclipse@default:default,org.eclipse.platform.doc.user@default:default,org.eclipse.ecf.provider.filetransfer.httpclient.ssl@default:false,commonj.sdo@default:default,org.apache.commons.httpclient@default:default,org.eclipse.equinox.simpleconfigurator@1:true,org.apache.commons.jxpath@default:default,org.eclipse.core.net.linux.x86@default:false,org.eclipse.ui.presentations.r21@default:default,org.eclipse.wst.standard.schemas@default:default,org.eclipse.equinox.launcher.win32.win32.x86_64@default:false,org.eclipse.ui.intro.universal@default:default,org.eclipse.dstore.extra@default:default,org.eclipse.team.cvs.ssh2@default:default,org.eclipse.jsch.core@default:default,org.eclipse.wst.jsdt.doc@default:default,org.eclipse.cvs@default:default,javax.wsdl*1.5.1.v200806030408@default:default,org.apache.jasper@default:default,javax.persistence@default:default,org.eclipse.ui.navigator.resources@default:default,org.eclipse.core.net@default:default,org.apache.xml.resolver@default:default,javax.mail*1.4.0.v200905040518@default:default,org.eclipse.jface@default:default,org.eclipse.equinox.p2.repository.tools@default:default,org.eclipse.equinox.p2.ui.sdk@default:default,org.eclipse.equinox.launcher@default:default,org.eclipse.equinox.frameworkadmin.equinox@default:default,org.eclipse.emf.ecore.change@default:default,org.eclipse.wst.command.env.infopop@default:default,org.eclipse.emf.mapping.ecore2xml@default:default,org.eclipse.debug.core@default:default,org.eclipse.core.resources.compatibility@default:false,org.eclipse.emf@default:default,javax.transaction@default:false,org.eclipse.team.cvs.ui@default:default,org.eclipse.emf.edit@default:default,org.eclipse.ecf@default:default,org.eclipse.core.filebuffers@default:default,org.eclipse.ui.intro@default:default,org.eclipse.wst.common.core@default:default,org.mortbay.jetty.util@default:default,org.eclipse.equinox.p2.artifact.repository@default:default,org.eclipse.wst.common.frameworks@default:default,org.eclipse.wst.common.environment@default:default,com.ibm.icu@default:default,com.jcraft.jsch@default:default,org.eclipse.wst.css.core@default:default,org.eclipse.emf.common@default:default,org.eclipse.equinox.p2.engine@default:default,org.eclipse.equinox.common@2:true,org.apache.commons.codec@default:default,org.eclipse.equinox.p2.jarprocessor@default:default,org.eclipse.equinox.p2.updatesite@default:default,org.eclipse.wst.common.emfworkbench.integration@default:default,org.eclipse.search@default:default,javax.xml.soap@default:default,org.eclipse.equinox.p2.director.app@default:default,org.eclipse.ui.ide@default:default,org.eclipse.wst.xml.ui@default:default,org.eclipse.ui.views.properties.tabbed@default:default,org.eclipse.ecf.provider.filetransfer@default:default,org.eclipse.wst.html.ui@default:default,org.eclipse.emf.common.ui@default:default,org.eclipse.swt.win32.win32.x86_64@default:false,org.eclipse.equinox.simpleconfigurator.manipulator@default:default,org.eclipse.wst.xml.xpath2.processor@default:default,org.eclipse.core.databinding.observable@default:default,org.eclipse.jem@default:default,org.eclipse.ui.ide.application@default:default,org.eclipse.team.cvs.ssh@default:default,org.apache.commons.lang*2.3.0.v200803061910@default:default,org.eclipse.wst.xml.xpath.ui@default:default,org.eclipse.ui.console@default:default,org.eclipse.net4j.jms.api@default:default,org.eclipse.equinox.p2.extensionlocation@default:default,org.eclipse.core.databinding.property@default:default,org.eclipse.core.databinding@default:default,org.objectweb.asm@default:default,org.apache.commons.net@default:default,java_cup.runtime@default:default,org.eclipse.ui.cheatsheets@default:default,org.eclipse.epp.package.jee@default:default,org.eclipse.jface.databinding@default:default,org.eclipse.equinox.jsp.jasper@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.equinox.http.jetty@default:default,org.jdom@default:default,org.eclipse.ui.forms@default:default,org.eclipse.wst.jsdt.web.core@default:default,org.eclipse.core.resources@default:default,org.eclipse.wst.html.core@default:default,org.eclipse.ui.views.log@default:default,javax.xml.stream@default:default,org.eclipse.ui.editors@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.wst.validation@default:default,org.eclipse.emf.mapping.ui@default:default,org.eclipse.wst.jsdt.ui@default:default,org.eclipse.ui.workbench.texteditor@default:default,org.eclipse.equinox.util@default:default,org.eclipse.wst.sse.doc.user@default:default,org.eclipse.equinox.jsp.jasper.registry@default:default,org.eclipse.equinox.security.ui@default:default,org.eclipse.team.cvs.core@default:default,org.eclipse.ecf.identity@default:default,org.eclipse.core.filesystem.linux.x86@default:false,javax.xml.bind*2.0.0.v20080604-1500@default:default,org.eclipse.help.webapp@default:default,org.eclipse.text@default:default,org.eclipse.equinox.security@default:default,org.eclipse.equinox.frameworkadmin@default:default,org.eclipse.emf.ecore.edit@default:default,org.eclipse.wst.common.project.facet.core@default:default,org.eclipse.equinox.p2.director@default:default,org.eclipse.wst.sse.ui.infopop@default:default,org.eclipse.wst.internet.cache@default:default,org.eclipse.equinox.http.registry@default:default,org.eclipse.wst.common.infopop@default:default,org.eclipse.core.runtime.compatibility.registry@default:false,org.eclipse.update.core.linux@default:false,org.apache.xml.serializer@default:default,org.apache.commons.collections@default:default,org.eclipse.ltk.ui.refactoring@default:default,org.eclipse.jem.util@default:default,org.eclipse.wst.common.modulecore@default:default,org.eclipse.osgi.services@default:default,org.eclipse.wst.internet.monitor.ui@default:default,org.eclipse.wst.command.env@default:default,org.apache.bcel@default:default,org.apache.commons.discovery@default:default,javax.wsdl*1.6.2.v200806030405@default:default,javax.servlet@default:default,org.eclipse.core.expressions@default:default,org.apache.lucene@default:default,org.eclipse.wst.css.ui@default:default,org.mozilla.xulrunner@default:default,org.eclipse.equinox.app@default:default,org.eclipse.core.commands@default:default,org.hamcrest.core@default:default,org.eclipse.equinox.p2.metadata.generator@default:default,org.eclipse.jface.text@default:default,javax.xml.rpc@default:default,org.eclipse.equinox.p2.reconciler.dropins@default:default,org.eclipse.osgi.util@default:default,org.eclipse.equinox.p2.touchpoint.natives@default:default,javax.xml.bind*2.1.9.v200905050702@default:default,javax.xml@default:default,org.eclipse.equinox.p2.directorywatcher@default:default,org.eclipse.wst.xml.ui.infopop@default:default,org.apache.log4j@default:default,org.eclipse.core.filesystem@default:default,org.eclipse.osgi@-1:true,org.eclipse.ecf.provider.filetransfer.httpclient@default:default,org.eclipse.ui.workbench@default:default,org.eclipse.help.base@default:default,org.eclipse.wst.xml.core@default:default,org.mortbay.jetty.server@default:default,org.eclipse.help.ui@default:default,org.eclipse.wst.common.ui@default:default,org.eclipse.equinox.concurrent@default:default,org.apache.lucene.analysis@default:default,org.eclipse.wst.common.emf@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.core.runtime.compatibility.auth@default:default,javax.activation*1.1.0.v200906290531@default:default,org.eclipse.wst.sse.core@default:default,org.eclipse.ui.net@default:default,org.sat4j.pb@default:default,org.eclipse.wst.xml.xpath.core@default:default,org.eclipse.rcp@default:default,org.eclipse.help.appserver@default:default,org.eclipse.equinox.p2.metadata@default:default,org.eclipse.emf.databinding@default:default,org.eclipse.wst.command.env.doc.user@default:default,org.eclipse.wst.common.frameworks.ui@default:default,org.eclipse.swt@default:default,org.sat4j.core@default:default,org.eclipse.ui.externaltools@default:default,org.eclipse.dstore.core@default:default,org.eclipse.ecf.ssl@default:false,org.eclipse.update.scheduler@default:default,org.eclipse.emf.mapping.ecore@default:default,org.eclipse.wst.jsdt.support.ie@default:default,org.eclipse.wst.sse.ui@default:default,org.eclipse.ui.workbench.compatibility@default:false,org.eclipse.swt.win32.win32.x86@default:false,org.apache.xalan@default:default,org.apache.commons.el@default:default,org.eclipse.equinox.ds@1:true,org.eclipse.team.ui@default:default,org.eclipse.update.configurator@3:true,org.eclipse.equinox.p2.exemplarysetup@default:default,org.eclipse.wst.jsdt.support.firefox@default:default,org.eclipse.core.databinding.beans@default:default,org.eclipse.gef@default:default,org.eclipse.equinox.p2.console@default:default,org.eclipse.wst.jsdt.web.ui@default:default,org.eclipse.help@default:default,org.eclipse.jsch.ui@default:default,org.eclipse.emf.ecore@default:default"/>
-<stringAttribute key="selected_workspace_plugins" value="org.chromium.debug.core@default:default,org.chromium.sdk@default:default,org.symbian.tools.wrttools@default:default,org.symbian.tools.wrttools.product@default:default,org.symbian.tools.wrttools.debug.core@default:default,org.symbian.tools.wrttools.previewer@default:default,org.chromium.debug.ui@default:default"/>
+<stringAttribute key="selected_target_plugins" value="org.eclipse.wst.command.env@default:default,org.eclipse.ecf.ssl@default:false,org.eclipse.ui@default:default,org.eclipse.wst.sse.ui@default:default,org.eclipse.update.core.linux@default:false,org.apache.commons.discovery@default:default,org.eclipse.jface@default:default,org.eclipse.wst.jsdt.web.core@default:default,org.eclipse.equinox.p2.director.app@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.wst.sse.core@default:default,org.mortbay.jetty.util@default:default,org.eclipse.equinox.p2.ui.sdk@default:default,org.eclipse.dstore.extra@default:default,org.eclipse.wst.css.core@default:default,org.eclipse.team.cvs.ssh2@default:default,org.eclipse.update.scheduler@default:default,org.eclipse.core.runtime@default:true,org.eclipse.equinox.p2.console@default:default,org.eclipse.equinox.p2.metadata.repository@default:default,org.eclipse.ui.intro@default:default,org.eclipse.equinox.security.ui@default:default,org.eclipse.ecf@default:default,javax.wsdl*1.5.1.v200806030408@default:default,org.eclipse.swt@default:default,org.eclipse.equinox.p2.artifact.repository@default:default,org.eclipse.equinox.p2.ui@default:default,org.eclipse.core.runtime.compatibility.registry@default:false,org.mozilla.xulrunner.win32.win32.x86@default:false,org.eclipse.equinox.p2.touchpoint.natives@default:default,org.eclipse.ui.views.properties.tabbed@default:default,org.eclipse.ui.workbench.compatibility@default:false,org.eclipse.jem@default:default,org.eclipse.core.filesystem@default:default,org.eclipse.ui.ide@default:default,org.eclipse.core.filesystem.win32.x86@default:false,org.eclipse.compare.core@default:default,org.apache.oro@default:default,org.eclipse.wst.command.env.infopop@default:default,org.eclipse.equinox.jsp.jasper.registry@default:default,org.eclipse.osgi.util@default:default,org.eclipse.equinox.p2.metadata.generator@default:default,org.eclipse.equinox.concurrent@default:default,org.eclipse.epp.package.jee@default:default,javax.servlet@default:default,org.eclipse.team.cvs.ui@default:default,org.eclipse.update.core@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.ui.navigator@default:default,org.eclipse.wst.validation.infopop@default:default,org.eclipse.ltk.ui.refactoring@default:default,org.eclipse.equinox.p2.director@default:default,org.eclipse.equinox.security@default:default,org.eclipse.wst.css.ui@default:default,javax.xml.bind*2.1.9.v200905050702@default:default,org.eclipse.wst.html.core@default:default,org.eclipse.core.expressions@default:default,org.eclipse.team.cvs.core@default:default,org.eclipse.wst.internet.cache@default:default,org.eclipse.wst.common.core@default:default,org.eclipse.equinox.p2.updatechecker@default:default,org.eclipse.core.filesystem.linux.x86@default:false,com.jcraft.jsch@default:default,org.eclipse.swt.win32.win32.x86_64@default:false,javax.xml.soap@default:default,org.apache.axis@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.search@default:default,org.eclipse.ecf.provider.filetransfer.ssl@default:false,org.eclipse.emf.edit@default:default,org.eclipse.equinox.launcher.win32.win32.x86_64@default:false,org.eclipse.ui.forms@default:default,org.eclipse.ui.browser@default:default,org.eclipse.ui.cheatsheets@default:default,org.eclipse.update.configurator@3:true,org.eclipse.equinox.ds@1:true,org.eclipse.osgi.services@default:default,org.eclipse.emf.ecore.change@default:default,org.eclipse.core.filesystem.macosx@default:false,org.eclipse.core.variables@default:default,org.eclipse.debug.core@default:default,org.eclipse.emf.ecore.edit@default:default,org.eclipse.wst.common.uriresolver@default:default,org.eclipse.ecf.provider.filetransfer.httpclient@default:default,org.apache.xml.serializer@default:default,org.eclipse.ui.views@default:default,org.apache.lucene.analysis@default:default,org.eclipse.help.ui@default:default,org.mozilla.xpcom@default:default,org.eclipse.ui.net@default:default,org.eclipse.help.base@default:default,org.eclipse.emf.mapping.ecore2ecore@default:default,org.eclipse.ui.presentations.r21@default:default,org.eclipse.wst.sse.doc.user@default:default,org.eclipse.ltk.core.refactoring@default:default,org.mozilla.xulrunner@default:default,org.eclipse.debug.ui@default:default,org.eclipse.equinox.common@2:true,javax.mail*1.4.0.v200905040518@default:default,org.eclipse.wtp.epp.package.jee.intro@default:default,org.apache.log4j@default:default,org.apache.commons.codec@default:default,org.eclipse.gef@default:default,com.ibm.icu@default:default,org.eclipse.emf.databinding.edit@default:default,org.eclipse.core.resources.compatibility@default:false,org.hamcrest.core@default:default,org.eclipse.wst.jsdt.web.ui@default:default,org.eclipse.equinox.p2.touchpoint.eclipse@default:default,org.eclipse.core.databinding.observable@default:default,org.eclipse.wst.xml.core@default:default,org.eclipse.ecf.provider.filetransfer.httpclient.ssl@default:false,org.apache.velocity@default:default,org.eclipse.emf@default:default,org.eclipse.wst.jsdt.manipulation@default:default,org.eclipse.emf.databinding@default:default,org.eclipse.wst.command.env.core@default:default,org.eclipse.equinox.http.jetty@default:default,org.eclipse.wst.common.frameworks.ui@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.util@default:default,org.eclipse.emf.mapping.ecore2xml@default:default,org.eclipse.emf.ecore.change.edit@default:default,org.eclipse.ui.views.log@default:default,org.eclipse.ecf.filetransfer@default:default,org.eclipse.core.boot@default:default,org.eclipse.core.jobs@default:default,org.eclipse.equinox.frameworkadmin.equinox@default:default,org.eclipse.update.ui@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.wst.xml.xpath.ui@default:default,org.eclipse.wst.common.snippets@default:default,org.eclipse.wst.xml.xpath2.processor@default:default,org.eclipse.wst.standard.schemas@default:default,javax.transaction@default:false,commonj.sdo@default:default,org.eclipse.ui.ide.application@default:default,org.apache.jasper@default:default,org.eclipse.wst.internet.monitor.ui@default:default,org.eclipse.emf.mapping.ecore@default:default,org.eclipse.ui.externaltools@default:default,org.eclipse.emf.mapping.ecore.editor@default:default,org.eclipse.wst.common.environment@default:default,org.eclipse.dstore.core@default:default,org.eclipse.emf.mapping.ui@default:default,javax.activation*1.1.0.v200906290531@default:default,org.eclipse.ui.workbench@default:default,org.eclipse.wst.command.env.doc.user@default:default,org.eclipse.osgi@-1:true,org.eclipse.wst.common.project.facet.core@default:default,org.eclipse.swt.gtk.linux.x86@default:false,org.eclipse.core.commands@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.equinox.p2.reconciler.dropins@default:default,org.eclipse.wst.jsdt.core@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.team.ui@default:default,org.eclipse.equinox.p2.updatesite@default:default,org.eclipse.core.runtime.compatibility.auth@default:default,org.eclipse.jsch.core@default:default,org.eclipse.equinox.jsp.jasper@default:default,org.apache.xalan@default:default,org.eclipse.equinox.p2.garbagecollector@default:default,org.sat4j.pb@default:default,org.eclipse.equinox.p2.engine@default:default,org.apache.lucene@default:default,org.eclipse.ecf.identity@default:default,java_cup.runtime@default:default,org.eclipse.wst.html.ui.infopop@default:default,org.eclipse.core.net@default:default,javax.wsdl*1.6.2.v200806030405@default:default,javax.servlet.jsp@default:default,org.apache.bcel@default:default,org.apache.commons.collections@default:default,javax.persistence@default:default,org.eclipse.wst.common.emf@default:default,org.eclipse.wst.xml.ui@default:default,javax.xml.bind*2.0.0.v20080604-1500@default:default,org.eclipse.equinox.http.registry@default:default,org.apache.commons.lang*2.3.0.v200803061910@default:default,org.eclipse.help.appserver@default:default,org.eclipse.wst.doc.user@default:default,org.eclipse.ui.workbench.texteditor@default:default,org.eclipse.ui.console@default:default,org.eclipse.jface.databinding@default:default,org.eclipse.rcp@default:default,org.eclipse.platform.doc.user@default:default,org.eclipse.core.runtime.compatibility@default:default,org.eclipse.emf.mapping@default:default,org.eclipse.wst.sse.ui.infopop@default:default,org.eclipse.wst.common.emfworkbench.integration@default:default,org.apache.commons.jxpath@default:default,org.eclipse.equinox.launcher.win32.win32.x86@default:false,org.apache.commons.el@default:default,javax.xml@default:default,org.eclipse.wst.internet.monitor.core@default:default,org.eclipse.equinox.simpleconfigurator.manipulator@default:default,org.eclipse.core.databinding.beans@default:default,org.apache.commons.net@default:default,org.eclipse.help.webapp@default:default,org.eclipse.equinox.launcher.gtk.linux.x86@default:false,org.eclipse.swt.win32.win32.x86@default:false,org.eclipse.core.net.linux.x86@default:false,org.eclipse.team.core@default:default,org.eclipse.emf.common@default:default,javax.xml.rpc@default:default,org.apache.xerces@default:default,org.eclipse.wst.jsdt.support.firefox@default:default,org.eclipse.equinox.p2.publisher@default:default,org.eclipse.equinox.p2.core@default:default,org.eclipse.ui.navigator.resources@default:default,org.eclipse.emf.common.ui@default:default,org.eclipse.equinox.p2.extensionlocation@default:default,org.eclipse.wst.validation.ui@default:default,org.objectweb.asm@default:default,org.eclipse.wst.common.infopop@default:default,org.eclipse.equinox.launcher@default:default,org.eclipse.net4j.jms.api@default:default,org.eclipse.wst.jsdt.doc@default:default,org.eclipse.wst.html.ui@default:default,org.eclipse.equinox.p2.exemplarysetup@default:default,org.mortbay.jetty.server@default:default,org.eclipse.ui.intro.universal@default:default,org.eclipse.wst.jsdt.ui@default:default,org.eclipse.equinox.p2.metadata@default:default,org.eclipse.equinox.p2.repository.tools@default:default,org.eclipse.help@default:default,org.eclipse.wst.xml.ui.infopop@default:default,org.apache.commons.logging@default:default,javax.xml.stream@default:default,org.eclipse.core.databinding@default:default,org.eclipse.wst.jsdt.support.ie@default:default,org.eclipse.cvs@default:default,org.eclipse.emf.edit.ui@default:default,org.eclipse.platform@default:default,org.eclipse.equinox.p2.repository@default:default,org.eclipse.jem.util@default:default,org.eclipse.text@default:default,net.sourceforge.lpg.lpgjavaruntime@default:default,org.eclipse.wst.xml.xpath.core@default:default,org.eclipse.ui.editors@default:default,org.sat4j.core@default:default,org.eclipse.compare@default:default,org.eclipse.core.filebuffers@default:default,org.eclipse.core.resources@default:default,org.eclipse.equinox.frameworkadmin@default:default,org.eclipse.wst.common.frameworks@default:default,org.eclipse.equinox.p2.ui.sdk.scheduler@default:default,org.eclipse.wst.validation@default:default,org.eclipse.equinox.simpleconfigurator@1:true,org.eclipse.draw2d@default:default,org.eclipse.wst.common.ui@default:default,org.eclipse.jsch.ui@default:default,org.apache.commons.httpclient@default:default,org.eclipse.jface.text@default:default,org.eclipse.wst.common.modulecore@default:default,org.eclipse.wst.xmleditor.doc.user@default:default,org.eclipse.core.databinding.property@default:default,org.jdom@default:default,org.apache.xml.resolver@default:default,org.eclipse.team.cvs.ssh@default:default,org.eclipse.equinox.p2.jarprocessor@default:default,org.eclipse.ecf.provider.filetransfer@default:default,org.eclipse.equinox.p2.directorywatcher@default:default"/>
+<stringAttribute key="selected_workspace_plugins" value="org.chromium.debug.core@default:default,org.chromium.sdk@default:default,org.symbian.tools.wrttools.product@default:default,org.symbian.tools.wrttools.debug.core@default:default,org.symbian.tools.wrttools@default:default,org.symbian.tools.wrttools.previewer@default:default,org.chromium.debug.ui@default:default"/>
 <booleanAttribute key="show_selected_only" value="false"/>
 <booleanAttribute key="tracing" value="false"/>
 <booleanAttribute key="useDefaultConfig" value="true"/>
--- a/org.symbian.tools.wrttools/.classpath	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.symbian.tools.wrttools/.classpath	Wed Jan 27 15:59:22 2010 -0800
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry exported="true" kind="lib" path="lib/jtidy-8.0-20060801.131059-3.jar"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="cssvalidation-src/"/>
 	<classpathentry kind="src" path="cssvalidator-mods-src/"/>
 	<classpathentry exported="true" kind="lib" path="lib/tagsoup-1.2.jar"/>
+	<classpathentry exported="true" kind="lib" path="lib/jtidy-8.0-20060801.131059-3.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
--- a/org.symbian.tools.wrttools/build.properties	Wed Jan 27 15:47:03 2010 -0800
+++ b/org.symbian.tools.wrttools/build.properties	Wed Jan 27 15:59:22 2010 -0800
@@ -6,7 +6,6 @@
                .,\
                plugin.xml,\
                projecttemplates/,\
-               lib/,\
                licenses/,\
                icons/,\
                lib/jtidy-8.0-20060801.131059-3.jar
Binary file org.symbian.tools.wrttools/icons/Thumbs.db has changed