Home | History | Annotate | Download | only in front-end
      1 /*
      2  * Copyright (C) 2010 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 WebInspector.DebuggerModel = function()
     32 {
     33     this._debuggerPausedDetails = {};
     34     this._scripts = {};
     35 
     36     InspectorBackend.registerDomainDispatcher("Debugger", new WebInspector.DebuggerDispatcher(this));
     37 }
     38 
     39 WebInspector.DebuggerModel.Events = {
     40     DebuggerWasEnabled: "debugger-was-enabled",
     41     DebuggerWasDisabled: "debugger-was-disabled",
     42     DebuggerPaused: "debugger-paused",
     43     DebuggerResumed: "debugger-resumed",
     44     ParsedScriptSource: "parsed-script-source",
     45     FailedToParseScriptSource: "failed-to-parse-script-source",
     46     BreakpointResolved: "breakpoint-resolved",
     47     Reset: "reset"
     48 }
     49 
     50 WebInspector.DebuggerModel.prototype = {
     51     enableDebugger: function()
     52     {
     53         DebuggerAgent.enable();
     54     },
     55 
     56     disableDebugger: function()
     57     {
     58         DebuggerAgent.disable();
     59     },
     60 
     61     _debuggerWasEnabled: function()
     62     {
     63         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasEnabled);
     64     },
     65 
     66     _debuggerWasDisabled: function()
     67     {
     68         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasDisabled);
     69     },
     70 
     71     continueToLocation: function(location)
     72     {
     73         DebuggerAgent.continueToLocation(location);
     74     },
     75 
     76     setBreakpoint: function(url, lineNumber, columnNumber, condition, callback)
     77     {
     78         // Adjust column if needed.
     79         var minColumnNumber = 0;
     80         for (var id in this._scripts) {
     81             var script = this._scripts[id];
     82             if (url === script.sourceURL && lineNumber === script.lineOffset)
     83                 minColumnNumber = minColumnNumber ? Math.min(minColumnNumber, script.columnOffset) : script.columnOffset;
     84         }
     85         columnNumber = Math.max(columnNumber, minColumnNumber);
     86 
     87         function didSetBreakpoint(error, breakpointId, locations)
     88         {
     89             if (callback)
     90                 callback(error ? null : breakpointId, locations);
     91         }
     92         DebuggerAgent.setBreakpointByUrl(url, lineNumber, columnNumber, condition, didSetBreakpoint.bind(this));
     93     },
     94 
     95     setBreakpointBySourceId: function(location, condition, callback)
     96     {
     97         function didSetBreakpoint(error, breakpointId, actualLocation)
     98         {
     99             if (callback)
    100                 callback(error ? null : breakpointId, [actualLocation]);
    101         }
    102         DebuggerAgent.setBreakpoint(location, condition, didSetBreakpoint.bind(this));
    103     },
    104 
    105     removeBreakpoint: function(breakpointId, callback)
    106     {
    107         DebuggerAgent.removeBreakpoint(breakpointId, callback);
    108     },
    109 
    110     _breakpointResolved: function(breakpointId, location)
    111     {
    112         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointResolved, {breakpointId: breakpointId, location: location});
    113     },
    114 
    115     reset: function()
    116     {
    117         this._debuggerPausedDetails = {};
    118         this._scripts = {};
    119         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.Reset);
    120     },
    121 
    122     get scripts()
    123     {
    124         return this._scripts;
    125     },
    126 
    127     scriptForSourceID: function(sourceID)
    128     {
    129         return this._scripts[sourceID];
    130     },
    131 
    132     scriptsForURL: function(url)
    133     {
    134         return this.queryScripts(function(s) { return s.sourceURL === url; });
    135     },
    136 
    137     queryScripts: function(filter)
    138     {
    139         var scripts = [];
    140         for (var sourceID in this._scripts) {
    141             var script = this._scripts[sourceID];
    142             if (filter(script))
    143                 scripts.push(script);
    144         }
    145         return scripts;
    146     },
    147 
    148     editScriptSource: function(sourceID, newSource, callback)
    149     {
    150         this._scripts[sourceID].editSource(newSource, this._didEditScriptSource.bind(this, sourceID, newSource, callback));
    151     },
    152 
    153     _didEditScriptSource: function(sourceID, newSource, callback, error, callFrames)
    154     {
    155         if (!error && callFrames && callFrames.length)
    156             this._debuggerPausedDetails.callFrames = callFrames;
    157         callback(error);
    158     },
    159 
    160     get callFrames()
    161     {
    162         return this._debuggerPausedDetails.callFrames;
    163     },
    164 
    165     get debuggerPausedDetails()
    166     {
    167         return this._debuggerPausedDetails;
    168     },
    169 
    170     _pausedScript: function(details)
    171     {
    172         this._debuggerPausedDetails = details;
    173         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPaused, details);
    174     },
    175 
    176     _resumedScript: function()
    177     {
    178         this._debuggerPausedDetails = {};
    179         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed);
    180     },
    181 
    182     _parsedScriptSource: function(sourceID, sourceURL, lineOffset, columnOffset, length, isContentScript)
    183     {
    184         var script = new WebInspector.Script(sourceID, sourceURL, lineOffset, columnOffset, length, undefined, undefined, isContentScript);
    185         this._scripts[sourceID] = script;
    186         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ParsedScriptSource, script);
    187     },
    188 
    189     _failedToParseScriptSource: function(sourceURL, source, startingLine, errorLine, errorMessage)
    190     {
    191         var script = new WebInspector.Script(null, sourceURL, startingLine, errorLine, errorMessage, undefined);
    192         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, script);
    193     }
    194 }
    195 
    196 WebInspector.DebuggerModel.prototype.__proto__ = WebInspector.Object.prototype;
    197 
    198 WebInspector.DebuggerEventTypes = {
    199     JavaScriptPause: 0,
    200     JavaScriptBreakpoint: 1,
    201     NativeBreakpoint: 2
    202 };
    203 
    204 WebInspector.DebuggerDispatcher = function(debuggerModel)
    205 {
    206     this._debuggerModel = debuggerModel;
    207 }
    208 
    209 WebInspector.DebuggerDispatcher.prototype = {
    210     paused: function(details)
    211     {
    212         this._debuggerModel._pausedScript(details);
    213     },
    214 
    215     resumed: function()
    216     {
    217         this._debuggerModel._resumedScript();
    218     },
    219 
    220     debuggerWasEnabled: function()
    221     {
    222         this._debuggerModel._debuggerWasEnabled();
    223     },
    224 
    225     debuggerWasDisabled: function()
    226     {
    227         this._debuggerModel._debuggerWasDisabled();
    228     },
    229 
    230     scriptParsed: function(sourceID, sourceURL, lineOffset, columnOffset, length, isContentScript)
    231     {
    232         this._debuggerModel._parsedScriptSource(sourceID, sourceURL, lineOffset, columnOffset, length, isContentScript);
    233     },
    234 
    235     scriptFailedToParse: function(sourceURL, source, startingLine, errorLine, errorMessage)
    236     {
    237         this._debuggerModel._failedToParseScriptSource(sourceURL, source, startingLine, errorLine, errorMessage);
    238     },
    239 
    240     breakpointResolved: function(breakpointId, sourceID, lineNumber, columnNumber)
    241     {
    242         this._debuggerModel._breakpointResolved(breakpointId, sourceID, lineNumber, columnNumber);
    243     }
    244 }
    245