2010-12-22 Sheriff Bot <webkit.review.bot@gmail.com>
[WebKit-https.git] / WebCore / inspector / front-end / DebuggerModel.js
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     InspectorBackend.registerDomainDispatcher("Debugger", this);
34
35     this._breakpoints = {};
36     this._scripts = {};
37 }
38
39 WebInspector.DebuggerModel.Events = {
40     DebuggerPaused: "debugger-paused",
41     DebuggerResumed: "debugger-resumed",
42     ParsedScriptSource: "parsed-script-source",
43     FailedToParseScriptSource: "failed-to-parse-script-source",
44     BreakpointAdded: "breakpoint-added",
45 }
46
47 WebInspector.DebuggerModel.prototype = {
48     setOneTimeBreakpoint: function(sourceID, line)
49     {
50         var breakpoint = new WebInspector.Breakpoint(this, sourceID, undefined, line, true, undefined);
51         if (this._breakpoints[breakpoint.id])
52             return;
53         if (this._oneTimeBreakpoint)
54             InspectorBackend.removeBreakpoint(this._oneTimeBreakpoint.sourceID, this._oneTimeBreakpoint.line);
55         this._oneTimeBreakpoint = breakpoint;
56         // FIXME(40669): one time breakpoint will be persisted in inspector settings if not hit.
57         this._setBreakpointOnBackend(breakpoint, true);
58     },
59
60     removeOneTimeBreakpoint: function()
61     {
62         if (this._oneTimeBreakpoint) {
63             InspectorBackend.removeBreakpoint(this._oneTimeBreakpoint.sourceID, this._oneTimeBreakpoint.line);
64             delete this._oneTimeBreakpoint;
65         }
66     },
67
68     setBreakpoint: function(sourceID, line, enabled, condition)
69     {
70         var url = this._scripts[sourceID].sourceURL;
71         var breakpoint = this._setBreakpoint(sourceID, url, line, enabled, condition);
72         if (breakpoint)
73             this._setBreakpointOnBackend(breakpoint);
74     },
75
76     queryBreakpoints: function(filter)
77     {
78         var breakpoints = [];
79         for (var id in this._breakpoints) {
80            var breakpoint = this._breakpoints[id];
81            if (filter(breakpoint))
82                breakpoints.push(breakpoint);
83         }
84         return breakpoints;
85     },
86
87     findBreakpoint: function(sourceID, lineNumber)
88     {
89         var breakpointId = WebInspector.Breakpoint.jsBreakpointId(sourceID, lineNumber);
90         return this._breakpoints[breakpointId];
91     },
92
93     reset: function()
94     {
95         this._breakpoints = {};
96         delete this._oneTimeBreakpoint;
97         this._scripts = {};
98     },
99
100     _setBreakpoint: function(sourceID, url, line, enabled, condition)
101     {
102         var breakpoint = new WebInspector.Breakpoint(this, sourceID, url, line, enabled, condition);
103         if (this._breakpoints[breakpoint.id])
104             return;
105         if (this._oneTimeBreakpoint && (this._oneTimeBreakpoint.id == breakpoint.id))
106             delete this._oneTimeBreakpoint;
107         this._breakpoints[breakpoint.id] = breakpoint;
108         breakpoint.addEventListener("removed", this._breakpointRemoved, this);
109         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointAdded, breakpoint);
110         return breakpoint;
111     },
112
113     _breakpointRemoved: function(event)
114     {
115         delete this._breakpoints[event.target.id];
116     },
117
118     _setBreakpointOnBackend: function(breakpoint, isOneTime)
119     {
120         function didSetBreakpoint(success, line)
121         {
122             if (success && line == breakpoint.line)
123                 return;
124             if (isOneTime) {
125                 if (success)
126                     this._oneTimeBreakpoint.line = line;
127                 else
128                     delete this._oneTimeBreakpoint;
129             } else {
130                 breakpoint.remove();
131                 if (success)
132                     this._setBreakpoint(breakpoint.sourceID, breakpoint.url, line, breakpoint.enabled, breakpoint.condition);
133             }
134         }
135         InspectorBackend.setBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.enabled, breakpoint.condition, didSetBreakpoint.bind(this));
136     },
137
138     scriptForSourceID: function(sourceID)
139     {
140         return this._scripts[sourceID];
141     },
142
143     scriptsForURL: function(url)
144     {
145         return this.queryScripts(function(s) { return s.sourceURL === url; });
146     },
147
148     queryScripts: function(filter)
149     {
150         var scripts = [];
151         for (var sourceID in this._scripts) {
152             var script = this._scripts[sourceID];
153             if (filter(script))
154                 scripts.push(script);
155         }
156         return scripts;
157     },
158
159     // All the methods below are InspectorBackend notification handlers.
160
161     breakpointRestored: function(sourceID, url, line, enabled, condition)
162     {
163         this._setBreakpoint(sourceID, url, line, enabled, condition);
164     },
165
166     pausedScript: function(details)
167     {
168         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPaused, details);
169
170         if (details.eventType === WebInspector.DebuggerEventTypes.JavaScriptPause || details.eventType === WebInspector.DebuggerEventTypes.NativeBreakpoint)
171             return;
172
173         var breakpoint = this.findBreakpoint(details.callFrames[0].sourceID, details.callFrames[0].line);
174         if (!breakpoint)
175             return;
176         breakpoint.hit = true;
177         this._lastHitBreakpoint = breakpoint;
178     },
179
180     resumedScript: function()
181     {
182         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed);
183
184         if (!this._lastHitBreakpoint)
185             return;
186         this._lastHitBreakpoint.hit = false;
187         delete this._lastHitBreakpoint;
188     },
189
190     attachDebuggerWhenShown: function()
191     {
192         WebInspector.panels.scripts.attachDebuggerWhenShown();
193     },
194
195     debuggerWasEnabled: function()
196     {
197         WebInspector.panels.scripts.debuggerWasEnabled();
198     },
199
200     debuggerWasDisabled: function()
201     {
202         WebInspector.panels.scripts.debuggerWasDisabled();
203     },
204
205     parsedScriptSource: function(sourceID, sourceURL, source, startingLine, scriptWorldType)
206     {
207         var script = new WebInspector.Script(sourceID, sourceURL, source, startingLine, undefined, undefined, scriptWorldType);
208         this._scripts[sourceID] = script;
209         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ParsedScriptSource, sourceID);
210     },
211
212     failedToParseScriptSource: function(sourceURL, source, startingLine, errorLine, errorMessage)
213     {
214         var script = new WebInspector.Script(null, sourceURL, source, startingLine, errorLine, errorMessage, undefined);
215         this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, script);
216     },
217
218     didCreateWorker: function()
219     {
220         var workersPane = WebInspector.panels.scripts.sidebarPanes.workers;
221         workersPane.addWorker.apply(workersPane, arguments);
222     },
223
224     didDestroyWorker: function()
225     {
226         var workersPane = WebInspector.panels.scripts.sidebarPanes.workers;
227         workersPane.removeWorker.apply(workersPane, arguments);
228     }
229 }
230
231 WebInspector.DebuggerModel.prototype.__proto__ = WebInspector.Object.prototype;
232
233 WebInspector.DebuggerEventTypes = {
234     JavaScriptPause: 0,
235     JavaScriptBreakpoint: 1,
236     NativeBreakpoint: 2
237 };