org.chromium.debug.core/src/org/chromium/debug/core/model/VProjectWorkspaceBridge.java
changeset 355 8726e95bcbba
parent 276 f2f4a1259de8
equal deleted inserted replaced
354:0bceeb415e7f 355:8726e95bcbba
     5 package org.chromium.debug.core.model;
     5 package org.chromium.debug.core.model;
     6 
     6 
     7 import java.util.Collection;
     7 import java.util.Collection;
     8 
     8 
     9 import org.chromium.debug.core.ChromiumDebugPlugin;
     9 import org.chromium.debug.core.ChromiumDebugPlugin;
       
    10 import org.chromium.debug.core.ChromiumSourceDirector;
       
    11 import org.chromium.debug.core.model.BreakpointSynchronizer.Callback;
    10 import org.chromium.debug.core.util.ChromiumDebugPluginUtil;
    12 import org.chromium.debug.core.util.ChromiumDebugPluginUtil;
    11 import org.chromium.sdk.Breakpoint;
    13 import org.chromium.sdk.Breakpoint;
    12 import org.chromium.sdk.CallFrame;
    14 import org.chromium.sdk.CallFrame;
    13 import org.chromium.sdk.DebugContext;
    15 import org.chromium.sdk.DebugContext;
    14 import org.chromium.sdk.ExceptionData;
    16 import org.chromium.sdk.ExceptionData;
    15 import org.chromium.sdk.JavascriptVm;
    17 import org.chromium.sdk.JavascriptVm;
    16 import org.chromium.sdk.Script;
    18 import org.chromium.sdk.Script;
    17 import org.chromium.sdk.JavascriptVm.BreakpointCallback;
    19 import org.chromium.sdk.SyncCallback;
    18 import org.chromium.sdk.JavascriptVm.ScriptsCallback;
    20 import org.chromium.sdk.JavascriptVm.ScriptsCallback;
    19 import org.eclipse.core.resources.IFile;
    21 import org.eclipse.core.resources.IFile;
    20 import org.eclipse.core.resources.IMarkerDelta;
    22 import org.eclipse.core.resources.IMarkerDelta;
    21 import org.eclipse.core.resources.IProject;
    23 import org.eclipse.core.resources.IProject;
    22 import org.eclipse.core.runtime.CoreException;
    24 import org.eclipse.core.runtime.CoreException;
    23 import org.eclipse.debug.core.DebugException;
    25 import org.eclipse.debug.core.DebugException;
    24 import org.eclipse.debug.core.DebugPlugin;
       
    25 import org.eclipse.debug.core.IBreakpointManager;
       
    26 import org.eclipse.debug.core.ILaunch;
    26 import org.eclipse.debug.core.ILaunch;
    27 import org.eclipse.debug.core.model.IBreakpoint;
    27 import org.eclipse.debug.core.model.IBreakpoint;
    28 import org.eclipse.debug.core.model.ISourceLocator;
       
    29 import org.eclipse.debug.core.model.IStackFrame;
       
    30 import org.eclipse.osgi.util.NLS;
    28 import org.eclipse.osgi.util.NLS;
    31 
    29 
    32 /**
    30 /**
    33  * Virtual project-supporting implementation of {@link WorkspaceBridge}.
    31  * Virtual project-supporting implementation of {@link WorkspaceBridge}.
    34  */
    32  */
    59   }
    57   }
    60 
    58 
    61   private final IProject debugProject;
    59   private final IProject debugProject;
    62   private final JavascriptVm javascriptVm;
    60   private final JavascriptVm javascriptVm;
    63   private final ResourceManager resourceManager;
    61   private final ResourceManager resourceManager;
    64   private final BreakpointRegistry breakpointRegistry = new BreakpointRegistry();
       
    65   private final DebugTargetImpl debugTargetImpl;
    62   private final DebugTargetImpl debugTargetImpl;
       
    63   private final BreakpointMap.InTargetMap breakpointInTargetMap = new BreakpointMap.InTargetMap();
       
    64   private final ChromiumSourceDirector sourceDirector;
    66 
    65 
    67   public VProjectWorkspaceBridge(String projectName, DebugTargetImpl debugTargetImpl,
    66   public VProjectWorkspaceBridge(String projectName, DebugTargetImpl debugTargetImpl,
    68       JavascriptVm javascriptVm) {
    67       JavascriptVm javascriptVm) {
    69     this.debugTargetImpl = debugTargetImpl;
    68     this.debugTargetImpl = debugTargetImpl;
    70     this.javascriptVm = javascriptVm;
    69     this.javascriptVm = javascriptVm;
    71     this.debugProject = ChromiumDebugPluginUtil.createEmptyProject(projectName);
    70     this.debugProject = ChromiumDebugPluginUtil.createEmptyProject(projectName);
    72     this.resourceManager = new ResourceManager(debugProject, breakpointRegistry);
    71     this.resourceManager = new ResourceManager(debugProject);
       
    72 
    73     ILaunch launch = debugTargetImpl.getLaunch();
    73     ILaunch launch = debugTargetImpl.getLaunch();
    74     launch.setSourceLocator(sourceLocator);
    74 
       
    75     sourceDirector = (ChromiumSourceDirector) launch.getSourceLocator();
       
    76     sourceDirector.initializeVProjectContainers(debugProject, resourceManager);
       
    77   }
       
    78 
       
    79   public void synchronizeBreakpoints(BreakpointSynchronizer.Direction direction,
       
    80       Callback callback) {
       
    81     BreakpointSynchronizer synchronizer = new BreakpointSynchronizer(javascriptVm,
       
    82         breakpointInTargetMap, sourceDirector, breakpointHandler, DEBUG_MODEL_ID);
       
    83     synchronizer.syncBreakpoints(direction, callback);
    75   }
    84   }
    76 
    85 
    77   public void launchRemoved() {
    86   public void launchRemoved() {
    78     if (debugProject != null) {
    87     if (debugProject != null) {
    79       ChromiumDebugPluginUtil.deleteVirtualProjectAsync(debugProject);
    88       ChromiumDebugPluginUtil.deleteVirtualProjectAsync(debugProject);
    80     }
    89     }
    81   }
    90   }
    82 
    91 
    83   public void beforeDetach() {
    92   public void beforeDetach() {
    84     IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
       
    85     IBreakpoint[] breakpoints =
       
    86         breakpointManager.getBreakpoints(DEBUG_MODEL_ID);
       
    87     for (IBreakpoint bp : breakpoints) {
       
    88       ChromiumLineBreakpoint clb = (ChromiumLineBreakpoint) bp;
       
    89       if (clb.getBrowserBreakpoint() != null &&
       
    90           clb.getBrowserBreakpoint().getId() != Breakpoint.INVALID_ID) {
       
    91         clb.getBrowserBreakpoint().clear(null);
       
    92       }
       
    93     }
       
    94     try {
       
    95       breakpointManager.removeBreakpoints(breakpoints, true);
       
    96     } catch (CoreException e) {
       
    97       ChromiumDebugPlugin.log(e);
       
    98     }
       
    99   }
    93   }
   100 
    94 
   101   public void handleVmResetEvent() {
    95   public void handleVmResetEvent() {
   102     resourceManager.clear();
    96     resourceManager.clear();
   103   }
    97   }
   121         }
   115         }
   122       }
   116       }
   123     });
   117     });
   124   }
   118   }
   125 
   119 
   126   public IFile getScriptResource(Script script) {
   120   public VmResource findVmResourceFromWorkspaceFile(IFile resource) throws CoreException {
   127     return resourceManager.getResource(script);
   121     VmResourceId id = findVmResourceIdFromWorkspaceFile(resource);
       
   122     if (id == null) {
       
   123       return null;
       
   124     }
       
   125     return resourceManager.getVmResource(id);
       
   126   }
       
   127 
       
   128   private VmResourceId findVmResourceIdFromWorkspaceFile(IFile resource) throws CoreException {
       
   129     return sourceDirector.getReverseSourceLookup().findVmResource(resource);
       
   130   }
       
   131 
       
   132   public void reloadScript(Script script) {
       
   133     resourceManager.reloadScript(script);
   128   }
   134   }
   129 
   135 
   130   public BreakpointHandler getBreakpointHandler() {
   136   public BreakpointHandler getBreakpointHandler() {
   131     return breakpointHandler;
   137     return breakpointHandler;
   132   }
   138   }
   133 
   139 
   134   private final BreakpointHandler breakpointHandler = new BreakpointHandler() {
   140   private final BreakpointHandlerImpl breakpointHandler = new BreakpointHandlerImpl();
       
   141 
       
   142   private class BreakpointHandlerImpl implements BreakpointHandler,
       
   143       BreakpointSynchronizer.BreakpointHelper {
   135     public boolean supportsBreakpoint(IBreakpoint breakpoint) {
   144     public boolean supportsBreakpoint(IBreakpoint breakpoint) {
   136       return DEBUG_MODEL_ID.equals(breakpoint.getModelIdentifier()) &&
   145       return DEBUG_MODEL_ID.equals(breakpoint.getModelIdentifier()) &&
   137           !debugTargetImpl.isDisconnected();
   146           !debugTargetImpl.isDisconnected();
   138     }
   147     }
       
   148 
       
   149     public ChromiumLineBreakpoint tryCastBreakpoint(IBreakpoint breakpoint) {
       
   150       if (!supportsBreakpoint(breakpoint)) {
       
   151         return null;
       
   152       }
       
   153       if (breakpoint instanceof ChromiumLineBreakpoint == false) {
       
   154         return null;
       
   155       }
       
   156       return (ChromiumLineBreakpoint) breakpoint;
       
   157     }
       
   158 
   139     public void breakpointAdded(IBreakpoint breakpoint) {
   159     public void breakpointAdded(IBreakpoint breakpoint) {
   140       if (!supportsBreakpoint(breakpoint)) {
   160       ChromiumLineBreakpoint lineBreakpoint = tryCastBreakpoint(breakpoint);
   141         return;
   161       if (lineBreakpoint == null) {
   142       }
   162         return;
   143       try {
   163       }
   144         if (breakpoint.isEnabled()) {
   164       if (ChromiumLineBreakpoint.getIgnoreList().contains(breakpoint)) {
   145           // Class cast is ensured by the supportsBreakpoint implementation
   165         return;
   146           final ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
   166       }
   147           IFile file = (IFile) breakpoint.getMarker().getResource();
   167       if (!lineBreakpoint.isEnabled()) {
   148           if (resourceManager.isAddingFile(file)) {
   168         return;
   149             return; // restoring breakpoints in progress
   169       }
       
   170       IFile file = (IFile) lineBreakpoint.getMarker().getResource();
       
   171       VmResourceId vmResourceId;
       
   172       try {
       
   173         vmResourceId = findVmResourceIdFromWorkspaceFile(file);
       
   174       } catch (CoreException e) {
       
   175         ChromiumDebugPlugin.log(
       
   176             new Exception("Failed to resolve script for the file " + file, e)); //$NON-NLS-1$
       
   177         return;
       
   178       }
       
   179       if (vmResourceId == null) {
       
   180         // Might be a script from a different debug target
       
   181         return;
       
   182       }
       
   183 
       
   184       createBreakpointOnRemote(lineBreakpoint, vmResourceId, null, null);
       
   185     }
       
   186 
       
   187     public void createBreakpointOnRemote(final ChromiumLineBreakpoint lineBreakpoint,
       
   188         final VmResourceId vmResourceId,
       
   189         final CreateCallback createCallback, SyncCallback syncCallback) {
       
   190       try {
       
   191         ChromiumLineBreakpoint.Helper.CreateOnRemoveCallback callback =
       
   192             new ChromiumLineBreakpoint.Helper.CreateOnRemoveCallback() {
       
   193           public void success(Breakpoint breakpoint) {
       
   194             breakpointInTargetMap.add(breakpoint, lineBreakpoint);
       
   195             if (createCallback != null) {
       
   196               createCallback.success();
       
   197             }
   150           }
   198           }
   151           final Script script = resourceManager.getScript(file);
   199           public void failure(String errorMessage) {
   152           if (script == null) {
   200             if (createCallback == null) {
   153             // Might be a script from a different debug target
   201               ChromiumDebugPlugin.logError(errorMessage);
   154             return;
   202             } else {
       
   203               createCallback.failure(new Exception(errorMessage));
       
   204             }
   155           }
   205           }
   156           // ILineBreakpoint lines are 1-based while V8 lines are 0-based
   206         };
   157           final int line = (lineBreakpoint.getLineNumber() - 1) + script.getStartLine();
   207 
   158           BreakpointCallback callback = new BreakpointCallback() {
   208         ChromiumLineBreakpoint.Helper.createOnRemote(lineBreakpoint, vmResourceId, debugTargetImpl,
   159             public void success(Breakpoint breakpoint) {
   209             callback, syncCallback);
   160               lineBreakpoint.setBreakpoint(breakpoint);
   210       } catch (CoreException e) {
   161               breakpointRegistry.add(script, line, breakpoint);
   211         ChromiumDebugPlugin.log(new Exception("Failed to create breakpoint in " + //$NON-NLS-1$
   162             }
   212             getTargetNameSafe(), e));
   163 
   213       }
   164             public void failure(String errorMessage) {
   214     }
   165               ChromiumDebugPlugin.logError(errorMessage);
   215 
   166             }
   216     public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
   167           };
   217       ChromiumLineBreakpoint lineBreakpoint = tryCastBreakpoint(breakpoint);
   168           if (script.getName() != null) {
   218       if (lineBreakpoint == null) {
   169             javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_NAME,
   219         return;
   170                 script.getName(),
   220       }
   171                 line,
   221       if (ChromiumLineBreakpoint.getIgnoreList().contains(lineBreakpoint)) {
   172                 Breakpoint.EMPTY_VALUE,
   222         return;
   173                 breakpoint.isEnabled(),
   223       }
   174                 lineBreakpoint.getCondition(),
   224       Breakpoint sdkBreakpoint = breakpointInTargetMap.getSdkBreakpoint(lineBreakpoint);
   175                 lineBreakpoint.getIgnoreCount(),
   225       if (sdkBreakpoint == null) {
   176                 callback);
   226         return;
   177           } else {
   227       }
   178             javascriptVm.setBreakpoint(Breakpoint.Type.SCRIPT_ID,
   228 
   179                 String.valueOf(script.getId()),
   229       try {
   180                 line,
   230         ChromiumLineBreakpoint.Helper.updateOnRemote(sdkBreakpoint, lineBreakpoint);
   181                 Breakpoint.EMPTY_VALUE,
   231       } catch (RuntimeException e) {
   182                 breakpoint.isEnabled(),
   232         ChromiumDebugPlugin.log(new Exception("Failed to change breakpoint in " + //$NON-NLS-1$
   183                 lineBreakpoint.getCondition(),
   233             getTargetNameSafe(), e));
   184                 lineBreakpoint.getIgnoreCount(),
   234       }
   185                 callback);
   235 
   186           }
   236     }
       
   237 
       
   238     public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
       
   239       ChromiumLineBreakpoint lineBreakpoint = tryCastBreakpoint(breakpoint);
       
   240       if (lineBreakpoint == null) {
       
   241         return;
       
   242       }
       
   243       if (ChromiumLineBreakpoint.getIgnoreList().contains(lineBreakpoint)) {
       
   244         return;
       
   245       }
       
   246 
       
   247       Breakpoint sdkBreakpoint = breakpointInTargetMap.getSdkBreakpoint(lineBreakpoint);
       
   248       if (sdkBreakpoint == null) {
       
   249         return;
       
   250       }
       
   251 
       
   252       try {
       
   253         if (!breakpoint.isEnabled()) {
       
   254           return;
   187         }
   255         }
   188       } catch (CoreException e) {
   256       } catch (CoreException e) {
   189         ChromiumDebugPlugin.log(e);
   257         ChromiumDebugPlugin.log(e);
   190       }
   258         return;
   191     }
   259       }
   192 
   260       JavascriptVm.BreakpointCallback callback = new JavascriptVm.BreakpointCallback() {
   193     public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
   261         public void failure(String errorMessage) {
   194       if (!supportsBreakpoint(breakpoint)) {
   262           ChromiumDebugPlugin.log(new Exception("Failed to remove breakpoint in " + //$NON-NLS-1$
   195         return;
   263               getTargetNameSafe() + ": " + errorMessage)); //$NON-NLS-1$
   196       }
   264         }
   197       // Class cast is ensured by the supportsBreakpoint implementation
   265         public void success(Breakpoint breakpoint) {
   198       ((ChromiumLineBreakpoint) breakpoint).changed();
   266         }
   199     }
   267       };
   200 
   268       try {
   201     public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
   269         sdkBreakpoint.clear(callback, null);
   202       if (!supportsBreakpoint(breakpoint)) {
   270       } catch (RuntimeException e) {
   203         return;
   271         ChromiumDebugPlugin.log(new Exception("Failed to remove breakpoint in " + //$NON-NLS-1$
   204       }
   272             getTargetNameSafe(), e));
   205       try {
   273       }
   206         if (breakpoint.isEnabled()) {
   274       breakpointInTargetMap.remove(lineBreakpoint);
   207           // Class cast is ensured by the supportsBreakpoint implementation
       
   208           ChromiumLineBreakpoint lineBreakpoint = (ChromiumLineBreakpoint) breakpoint;
       
   209           lineBreakpoint.clear();
       
   210           breakpointRegistry.remove(
       
   211               resourceManager.getScript((IFile) breakpoint.getMarker().getResource()),
       
   212               lineBreakpoint.getLineNumber() - 1,
       
   213               lineBreakpoint.getBrowserBreakpoint());
       
   214         }
       
   215       } catch (CoreException e) {
       
   216         ChromiumDebugPlugin.log(e);
       
   217       }
       
   218     }
   275     }
   219 
   276 
   220     public void breakpointsHit(Collection<? extends Breakpoint> breakpointsHit) {
   277     public void breakpointsHit(Collection<? extends Breakpoint> breakpointsHit) {
   221       if (breakpointsHit.isEmpty()) {
   278       if (breakpointsHit.isEmpty()) {
   222         return;
   279         return;
   223       }
   280       }
   224       IBreakpoint[] breakpoints =
   281 
   225           DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DEBUG_MODEL_ID);
   282       for (Breakpoint sdkBreakpoint : breakpointsHit) {
   226       for (IBreakpoint breakpoint : breakpoints) {
   283         ChromiumLineBreakpoint uiBreakpoint = breakpointInTargetMap.getUiBreakpoint(sdkBreakpoint);
   227         ChromiumLineBreakpoint jsBreakpoint = (ChromiumLineBreakpoint) breakpoint;
   284         if (uiBreakpoint != null) {
   228         if (breakpointsHit.contains(jsBreakpoint.getBrowserBreakpoint())) {
   285           uiBreakpoint.setIgnoreCount(-1); // reset ignore count as we've hit it
   229           jsBreakpoint.setIgnoreCount(-1); // reset ignore count as we've hit it
   286         }
   230         }
   287       }
   231       }
   288     }
   232     }
   289     private String getTargetNameSafe() {
   233   };
   290       try {
   234 
   291         return debugTargetImpl.getLaunch().getLaunchConfiguration().getName();
   235   public int getLineNumber(CallFrame stackFrame) {
   292       } catch (RuntimeException e) {
   236     // convert 0-based to 1-based
   293         return "<unknown>"; //$NON-NLS-1$
   237     return stackFrame.getLineNumber() + 1;
   294       }
   238   }
   295     }
   239   
   296   }
   240   /**
       
   241    * This very simple source locator works because we provide our own source files.
       
   242    * We'll have to try harder, once we link with resource js files.
       
   243    */
       
   244   private final ISourceLocator sourceLocator = new ISourceLocator() {
       
   245     public Object getSourceElement(IStackFrame stackFrame) {
       
   246       if (stackFrame instanceof StackFrame == false) {
       
   247         return null;
       
   248       }
       
   249       StackFrame jsStackFrame = (StackFrame) stackFrame;
       
   250 
       
   251       Script script = jsStackFrame.getCallFrame().getScript();
       
   252       if (script == null) {
       
   253         return null;
       
   254       }
       
   255 
       
   256       return resourceManager.getResource(script);
       
   257     }
       
   258   };
       
   259 
   297 
   260   private final static JsLabelProvider LABEL_PROVIDER = new JsLabelProvider() {
   298   private final static JsLabelProvider LABEL_PROVIDER = new JsLabelProvider() {
   261     public String getTargetLabel(DebugTargetImpl debugTarget) {
   299     public String getTargetLabel(DebugTargetImpl debugTarget) {
   262       JavascriptVmEmbedder vmEmbedder = debugTarget.getJavascriptEmbedder();
   300       JavascriptVmEmbedder vmEmbedder = debugTarget.getJavascriptEmbedder();
   263       if (vmEmbedder == null) {
   301       if (vmEmbedder == null) {
   296 
   334 
   297     public String getStackFrameLabel(StackFrame stackFrame) throws DebugException {
   335     public String getStackFrameLabel(StackFrame stackFrame) throws DebugException {
   298       CallFrame callFrame = stackFrame.getCallFrame();
   336       CallFrame callFrame = stackFrame.getCallFrame();
   299       String name = callFrame.getFunctionName();
   337       String name = callFrame.getFunctionName();
   300       Script script = callFrame.getScript();
   338       Script script = callFrame.getScript();
       
   339       String scriptName;
   301       if (script == null) {
   340       if (script == null) {
   302         return Messages.StackFrame_UnknownScriptName;
   341         scriptName = Messages.StackFrame_UnknownScriptName;
   303       }
   342       } else {
   304       int line = script.getStartLine() + stackFrame.getLineNumber();
   343         scriptName = VmResourceId.forScript(script).getEclipseSourceName();
       
   344       }
       
   345       int line = stackFrame.getLineNumber();
   305       if (line != -1) {
   346       if (line != -1) {
   306         name = NLS.bind(Messages.StackFrame_NameFormat,
   347         name = NLS.bind(Messages.StackFrame_NameFormat,
   307             new Object[] {name, script.getName(), line});
   348             new Object[] {name, scriptName, line});
   308       }
   349       }
   309       return name;
   350       return name;
   310     }
   351     }
   311   };
   352   };
   312 
       
   313 }
   353 }