org.chromium.debug.core/src/org/chromium/debug/core/model/VProjectWorkspaceBridge.java
changeset 52 f577ea64429e
child 115 d367ed1b2991
equal deleted inserted replaced
49:e64c52f5ee56 52:f577ea64429e
       
     1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style license that can be
       
     3 // found in the LICENSE file.
       
     4 
       
     5 package org.chromium.debug.core.model;
       
     6 
       
     7 import java.util.Collection;
       
     8 
       
     9 import org.chromium.debug.core.ChromiumDebugPlugin;
       
    10 import org.chromium.debug.core.util.ChromiumDebugPluginUtil;
       
    11 import org.chromium.sdk.Breakpoint;
       
    12 import org.chromium.sdk.CallFrame;
       
    13 import org.chromium.sdk.JavascriptVm;
       
    14 import org.chromium.sdk.Script;
       
    15 import org.chromium.sdk.JavascriptVm.BreakpointCallback;
       
    16 import org.chromium.sdk.JavascriptVm.ScriptsCallback;
       
    17 import org.eclipse.core.resources.IFile;
       
    18 import org.eclipse.core.resources.IMarkerDelta;
       
    19 import org.eclipse.core.resources.IProject;
       
    20 import org.eclipse.core.runtime.CoreException;
       
    21 import org.eclipse.debug.core.DebugException;
       
    22 import org.eclipse.debug.core.DebugPlugin;
       
    23 import org.eclipse.debug.core.IBreakpointManager;
       
    24 import org.eclipse.debug.core.ILaunch;
       
    25 import org.eclipse.debug.core.model.IBreakpoint;
       
    26 import org.eclipse.debug.core.model.ISourceLocator;
       
    27 import org.eclipse.debug.core.model.IStackFrame;
       
    28 import org.eclipse.osgi.util.NLS;
       
    29 
       
    30 /**
       
    31  * Virtual project-supporting implementation of {@link WorkspaceBridge}.
       
    32  */
       
    33 public class VProjectWorkspaceBridge implements WorkspaceBridge {
       
    34   /** The debug model ID. */
       
    35   public static final String DEBUG_MODEL_ID = "org.chromium.debug"; //$NON-NLS-1$
       
    36 
       
    37   public static class FactoryImpl implements Factory {
       
    38     private final String projectNameBase;
       
    39 
       
    40     public FactoryImpl(String projectNameBase) {
       
    41       this.projectNameBase = projectNameBase;
       
    42     }
       
    43 
       
    44     public WorkspaceBridge attachedToVm(DebugTargetImpl debugTargetImpl,
       
    45         JavascriptVm javascriptVm) {
       
    46       // We might want to add URL or something to project name.
       
    47       return new VProjectWorkspaceBridge(projectNameBase, debugTargetImpl, javascriptVm);
       
    48     }
       
    49 
       
    50     public String getDebugModelIdentifier() {
       
    51       return DEBUG_MODEL_ID;
       
    52     }
       
    53 
       
    54     public JsLabelProvider getLabelProvider() {
       
    55       return LABEL_PROVIDER;
       
    56     }
       
    57   }
       
    58 
       
    59   private final IProject debugProject;
       
    60   private final JavascriptVm javascriptVm;
       
    61   private final ResourceManager resourceManager;
       
    62   private final BreakpointRegistry breakpointRegistry = new BreakpointRegistry();
       
    63   private final DebugTargetImpl debugTargetImpl;
       
    64 
       
    65   public VProjectWorkspaceBridge(String projectName, DebugTargetImpl debugTargetImpl,
       
    66       JavascriptVm javascriptVm) {
       
    67     this.debugTargetImpl = debugTargetImpl;
       
    68     this.javascriptVm = javascriptVm;
       
    69     this.debugProject = ChromiumDebugPluginUtil.createEmptyProject(projectName);
       
    70     this.resourceManager = new ResourceManager(debugProject, breakpointRegistry);
       
    71     ILaunch launch = debugTargetImpl.getLaunch();
       
    72     launch.setSourceLocator(sourceLocator);
       
    73   }
       
    74 
       
    75   public void launchRemoved() {
       
    76     if (debugProject != null) {
       
    77       ChromiumDebugPluginUtil.deleteVirtualProjectAsync(debugProject);
       
    78     }
       
    79   }
       
    80 
       
    81   public void beforeDetach() {
       
    82     IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
       
    83     IBreakpoint[] breakpoints =
       
    84         breakpointManager.getBreakpoints(DEBUG_MODEL_ID);
       
    85     for (IBreakpoint bp : breakpoints) {
       
    86       ChromiumLineBreakpoint clb = (ChromiumLineBreakpoint) bp;
       
    87       if (clb.getBrowserBreakpoint() != null &&
       
    88           clb.getBrowserBreakpoint().getId() != Breakpoint.INVALID_ID) {
       
    89         clb.getBrowserBreakpoint().clear(null);
       
    90       }
       
    91     }
       
    92     try {
       
    93       breakpointManager.removeBreakpoints(breakpoints, true);
       
    94     } catch (CoreException e) {
       
    95       ChromiumDebugPlugin.log(e);
       
    96     }
       
    97   }
       
    98 
       
    99   public void handleVmResetEvent() {
       
   100     resourceManager.clear();
       
   101   }
       
   102 
       
   103   public void scriptLoaded(Script newScript) {
       
   104     resourceManager.addScript(newScript);
       
   105   }
       
   106 
       
   107   public void reloadScriptsAtStart() {
       
   108     javascriptVm.getScripts(new ScriptsCallback() {
       
   109       public void failure(String errorMessage) {
       
   110         ChromiumDebugPlugin.logError(errorMessage);
       
   111       }
       
   112 
       
   113       public void success(Collection<Script> scripts) {
       
   114         if (!javascriptVm.isAttached()) {
       
   115           return;
       
   116         }
       
   117         for (Script script : scripts) {
       
   118           resourceManager.addScript(script);
       
   119         }
       
   120       }
       
   121     });
       
   122   }
       
   123 
       
   124   public IFile getScriptResource(Script script) {
       
   125     return resourceManager.getResource(script);
       
   126   }
       
   127 
       
   128   public BreakpointHandler getBreakpointHandler() {
       
   129     return breakpointHandler;
       
   130   }
       
   131 
       
   132   private final BreakpointHandler breakpointHandler = new BreakpointHandler() {
       
   133     public boolean supportsBreakpoint(IBreakpoint breakpoint) {
       
   134       return DEBUG_MODEL_ID.equals(breakpoint.getModelIdentifier()) &&
       
   135           !debugTargetImpl.isDisconnected();
       
   136     }
       
   137     public void breakpointAdded(IBreakpoint breakpoint) {
       
   138       if (!supportsBreakpoint(breakpoint)) {
       
   139         return;
       
   140       }
       
   141       try {
       
   142         if (breakpoint.isEnabled()) {
       
   143           // Class cast is ensured by the supportsBreakpoint implementation
       
   144           final ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
       
   145           IFile file = (IFile) breakpoint.getMarker().getResource();
       
   146           if (resourceManager.isAddingFile(file)) {
       
   147             return; // restoring breakpoints in progress
       
   148           }
       
   149           final Script script = resourceManager.getScript(file);
       
   150           if (script == null) {
       
   151             // Might be a script from a different debug target
       
   152             return;
       
   153           }
       
   154           // ILineBreakpoint lines are 1-based while V8 lines are 0-based
       
   155           final int line = (lineBreakpoint.getLineNumber() - 1) + script.getStartLine();
       
   156           BreakpointCallback callback = new BreakpointCallback() {
       
   157             public void success(Breakpoint breakpoint) {
       
   158               lineBreakpoint.setBreakpoint(breakpoint);
       
   159               breakpointRegistry.add(script, line, breakpoint);
       
   160             }
       
   161 
       
   162             public void failure(String errorMessage) {
       
   163               ChromiumDebugPlugin.logError(errorMessage);
       
   164             }
       
   165           };
       
   166           if (script.getName() != null) {
       
   167             javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_NAME,
       
   168                 script.getName(),
       
   169                 line,
       
   170                 Breakpoint.EMPTY_VALUE,
       
   171                 breakpoint.isEnabled(),
       
   172                 lineBreakpoint.getCondition(),
       
   173                 lineBreakpoint.getIgnoreCount(),
       
   174                 callback);
       
   175           } else {
       
   176             javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_ID,
       
   177                 String.valueOf(script.getId()),
       
   178                 line,
       
   179                 Breakpoint.EMPTY_VALUE,
       
   180                 breakpoint.isEnabled(),
       
   181                 lineBreakpoint.getCondition(),
       
   182                 lineBreakpoint.getIgnoreCount(),
       
   183                 callback);
       
   184           }
       
   185         }
       
   186       } catch (CoreException e) {
       
   187         ChromiumDebugPlugin.log(e);
       
   188       }
       
   189     }
       
   190 
       
   191     public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
       
   192       if (!supportsBreakpoint(breakpoint)) {
       
   193         return;
       
   194       }
       
   195       // Class cast is ensured by the supportsBreakpoint implementation
       
   196       ((ChromiumLineBreakpoint) breakpoint).changed();
       
   197     }
       
   198 
       
   199     public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
       
   200       if (!supportsBreakpoint(breakpoint)) {
       
   201         return;
       
   202       }
       
   203       try {
       
   204         if (breakpoint.isEnabled()) {
       
   205           // Class cast is ensured by the supportsBreakpoint implementation
       
   206           ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
       
   207           lineBreakpoint.clear();
       
   208           breakpointRegistry.remove(
       
   209               resourceManager.getScript((IFile) breakpoint.getMarker().getResource()),
       
   210               lineBreakpoint.getLineNumber() - 1,
       
   211               lineBreakpoint.getBrowserBreakpoint());
       
   212         }
       
   213       } catch (CoreException e) {
       
   214         ChromiumDebugPlugin.log(e);
       
   215       }
       
   216     }
       
   217 
       
   218     public void breakpointsHit(Collection<? extends Breakpoint> breakpointsHit) {
       
   219       if (breakpointsHit.isEmpty()) {
       
   220         return;
       
   221       }
       
   222       IBreakpoint[] breakpoints =
       
   223           DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DEBUG_MODEL_ID);
       
   224       for (IBreakpoint breakpoint : breakpoints) {
       
   225         ChromiumLineBreakpoint jsBreakpoint = (ChromiumLineBreakpoint) breakpoint;
       
   226         if (breakpointsHit.contains(jsBreakpoint.getBrowserBreakpoint())) {
       
   227           jsBreakpoint.setIgnoreCount(-1); // reset ignore count as we've hit it
       
   228         }
       
   229       }
       
   230     }
       
   231   };
       
   232 
       
   233   /**
       
   234    * This very simple source locator works because we provide our own source files.
       
   235    * We'll have to try harder, once we link with resource js files.
       
   236    */
       
   237   private final ISourceLocator sourceLocator = new ISourceLocator() {
       
   238     public Object getSourceElement(IStackFrame stackFrame) {
       
   239       if (stackFrame instanceof StackFrame == false) {
       
   240         return null;
       
   241       }
       
   242       StackFrame jsStackFrame = (StackFrame) stackFrame;
       
   243 
       
   244       Script script = jsStackFrame.getCallFrame().getScript();
       
   245       if (script == null) {
       
   246         return null;
       
   247       }
       
   248 
       
   249       return resourceManager.getResource(script);
       
   250     }
       
   251   };
       
   252 
       
   253   private final static JsLabelProvider LABEL_PROVIDER = new JsLabelProvider() {
       
   254     public String getTargetLabel(DebugTargetImpl debugTarget) {
       
   255       JavascriptVmEmbedder vmEmbedder = debugTarget.getJavascriptEmbedder();
       
   256       if (vmEmbedder == null) {
       
   257         return ""; //$NON-NLS-1$
       
   258       }
       
   259       return vmEmbedder.getTargetName();
       
   260     }
       
   261 
       
   262     public String getThreadLabel(JavascriptThread thread) {
       
   263       String url = thread.getDebugTarget().getJavascriptEmbedder().getThreadName();
       
   264       return NLS.bind(Messages.JsThread_ThreadLabelFormat, (thread.isSuspended()
       
   265           ? Messages.JsThread_ThreadLabelSuspended
       
   266           : Messages.JsThread_ThreadLabelRunning), (url.length() > 0
       
   267           ? (" : " + url) : "")); //$NON-NLS-1$ //$NON-NLS-2$
       
   268     }
       
   269 
       
   270     public String getStackFrameLabel(StackFrame stackFrame) throws DebugException {
       
   271       CallFrame callFrame = stackFrame.getCallFrame();
       
   272       String name = callFrame.getFunctionName();
       
   273       Script script = callFrame.getScript();
       
   274       if (script == null) {
       
   275         return Messages.StackFrame_UnknownScriptName;
       
   276       }
       
   277       int line = script.getStartLine() + stackFrame.getLineNumber();
       
   278       if (line != -1) {
       
   279         name = NLS.bind(Messages.StackFrame_NameFormat,
       
   280             new Object[] {name, script.getName(), line});
       
   281       }
       
   282       return name;
       
   283     }
       
   284   };
       
   285 }