tizen beta release
[framework/web/webkit-efl.git] / debian / libwebkit-engine / usr / share / ewebkit-0 / webinspector / BreakpointManager.js
1 /*
2  * Copyright (C) 2011 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 /**
32  * @constructor
33  * @param {WebInspector.Setting} breakpointStorage
34  * @param {function(WebInspector.Breakpoint)} breakpointAddedDelegate
35  * @param {function(WebInspector.Breakpoint)} breakpointRemovedDelegate
36  * @param {WebInspector.DebuggerModel} debuggerModel
37  */
38 WebInspector.BreakpointManager = function(breakpointStorage, breakpointAddedDelegate, breakpointRemovedDelegate, debuggerModel)
39 {
40     this._breakpointStorage = breakpointStorage;
41     this._breakpointAddedDelegate = breakpointAddedDelegate;
42     this._breakpointRemovedDelegate = breakpointRemovedDelegate;
43     /**
44      * @type {Object.<string, Object.<string,WebInspector.Breakpoint>>}
45      */
46     this._breakpointsByUILocation = {};
47
48     this._debuggerModel = debuggerModel;
49
50     /**
51      * @type {Object.<DebuggerAgent.BreakpointId, WebInspector.Breakpoint>}
52      */
53     this._breakpointsByDebuggerId = {};
54     this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
55
56     var breakpoints = this._breakpointStorage.get();
57     for (var i = 0; i < breakpoints.length; ++i) {
58         var breakpoint = WebInspector.Breakpoint.deserialize(breakpoints[i]);
59         if (!this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber))
60             this._addBreakpointToUI(breakpoint);
61     }
62 }
63
64 WebInspector.BreakpointManager.prototype = {
65     /**
66      * @param {WebInspector.UISourceCode} uiSourceCode
67      */
68     uiSourceCodeAdded: function(uiSourceCode)
69     {
70         var breakpoints = this._breakpoints(uiSourceCode.id);
71         for (var lineNumber in breakpoints) {
72             var breakpoint = breakpoints[lineNumber];
73             breakpoint.uiSourceCode = uiSourceCode;
74             this._materializeBreakpoint(breakpoint, uiSourceCode.rawSourceCode.sourceMapping, uiSourceCode);
75             if (breakpoint._debuggerLocation)
76                 this._breakpointDebuggerLocationChanged(breakpoint);
77         }
78     },
79
80     /**
81      * @param {WebInspector.UISourceCode} uiSourceCode
82      */
83     breakpointsForUISourceCode: function(uiSourceCode)
84     {
85         return this._breakpoints(uiSourceCode.id);
86     },
87
88     /**
89      * @param {WebInspector.UISourceCode} uiSourceCode
90      * @param {number} lineNumber
91      * @param {string} condition
92      * @param {boolean} enabled
93      */
94     setBreakpoint: function(uiSourceCode, lineNumber, condition, enabled)
95     {
96         if (this._breakpoint(uiSourceCode.id, lineNumber))
97             return;
98
99         var persistent = !!uiSourceCode.url;
100         var breakpoint = new WebInspector.Breakpoint(uiSourceCode.id, lineNumber, condition, enabled, persistent);
101         breakpoint.uiSourceCode = uiSourceCode;
102         this._addBreakpointToUI(breakpoint);
103         this._materializeBreakpoint(breakpoint, uiSourceCode.rawSourceCode.sourceMapping, uiSourceCode);
104     },
105
106     /**
107      * @param {WebInspector.UISourceCode} uiSourceCode
108      * @param {number} lineNumber
109      */
110     removeBreakpoint: function(uiSourceCode, lineNumber)
111     {
112         var breakpoint = this._breakpoint(uiSourceCode.id, lineNumber);
113         if (!breakpoint)
114             return;
115         this._deleteBreakpointFromUI(breakpoint);
116         this._removeBreakpointFromDebugger(breakpoint);
117     },
118
119     /**
120      * @param {WebInspector.Breakpoint} breakpoint
121      * @param {WebInspector.RawSourceCode.SourceMapping} sourceMapping
122      * @param {WebInspector.UISourceCode} uiSourceCode
123      */
124     _materializeBreakpoint: function(breakpoint, sourceMapping, uiSourceCode)
125     {
126         if (!breakpoint.enabled || breakpoint._materialized)
127             return;
128
129         breakpoint._materialized = true;
130         var rawLocation = sourceMapping.uiLocationToRawLocation(uiSourceCode, breakpoint.lineNumber, 0);
131         this._setBreakpointInDebugger(breakpoint, rawLocation);
132     },
133
134     /**
135      * @param {WebInspector.Breakpoint} breakpoint
136      */
137     _breakpointDebuggerLocationChanged: function(breakpoint)
138     {
139         if (!breakpoint.uiSourceCode)
140             return;
141         var uiLocation = breakpoint.uiSourceCode.rawSourceCode.sourceMapping.rawLocationToUILocation(breakpoint._debuggerLocation);
142         if (uiLocation.lineNumber === breakpoint.lineNumber)
143             return;
144
145         if (!this._moveBreakpointInUI(breakpoint, uiLocation.lineNumber))
146             this._removeBreakpointFromDebugger(breakpoint);
147     },
148
149     /**
150      * @param {WebInspector.Breakpoint} breakpoint
151      */
152     _addBreakpointToUI: function(breakpoint)
153     {
154         console.assert(!this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber));
155         this._breakpoints(breakpoint.uiSourceCodeId)[breakpoint.lineNumber] = breakpoint;
156         this._saveBreakpoints();
157         this._breakpointAddedDelegate(breakpoint);
158     },
159
160     /**
161      * @param {WebInspector.Breakpoint} breakpoint
162      */
163     _deleteBreakpointFromUI: function(breakpoint)
164     {
165         console.assert(this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber) === breakpoint);
166         delete this._breakpoints(breakpoint.uiSourceCodeId)[breakpoint.lineNumber];
167         this._saveBreakpoints();
168         this._breakpointRemovedDelegate(breakpoint);
169     },
170
171     /**
172      * @param {WebInspector.Breakpoint} breakpoint
173      * @param {number} lineNumber
174      */
175     _moveBreakpointInUI: function(breakpoint, lineNumber)
176     {
177         this._deleteBreakpointFromUI(breakpoint);
178         if (this._breakpoint(breakpoint.uiSourceCodeId, lineNumber))
179             return false;
180         breakpoint.lineNumber = lineNumber;
181         this._addBreakpointToUI(breakpoint);
182         return true;
183     },
184
185     /**
186      * @param {string} uiSourceCodeId
187      */
188     _breakpoints: function(uiSourceCodeId)
189     {
190         if (!this._breakpointsByUILocation[uiSourceCodeId])
191             this._breakpointsByUILocation[uiSourceCodeId] = {};
192         return this._breakpointsByUILocation[uiSourceCodeId];
193     },
194
195     /**
196      * @param {string} uiSourceCodeId
197      * @param {number} lineNumber
198      */
199     _breakpoint: function(uiSourceCodeId, lineNumber)
200     {
201         return this._breakpoints(uiSourceCodeId)[lineNumber];
202     },
203
204     /**
205      * @param {function(WebInspector.Breakpoint)} handler
206      */
207     _forEachBreakpoint: function(handler)
208     {
209         for (var uiSourceCodeId in this._breakpointsByUILocation) {
210             var breakpoints = this._breakpointsByUILocation[uiSourceCodeId];
211             for (var lineNumber in breakpoints)
212                 handler(breakpoints[lineNumber]);
213         }
214     },
215
216     /**
217      * @param {WebInspector.Breakpoint} breakpoint
218      * @param {DebuggerAgent.Location} rawLocation
219      */
220     _setBreakpointInDebugger: function(breakpoint, rawLocation)
221     {
222         /**
223          * @this {WebInspector.BreakpointManager}
224          * @param {DebuggerAgent.BreakpointId} breakpointId
225          * @param {Array.<DebuggerAgent.Location>} locations
226          */
227         function didSetBreakpoint(breakpointId, locations)
228         {
229             if (breakpoint === this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber)) {
230                 if (!breakpointId) {
231                     this._deleteBreakpointFromUI(breakpoint);
232                     return;
233                 }
234             } else {
235                 if (breakpointId)
236                     this._debuggerModel.removeBreakpoint(breakpointId);
237                 return;
238             }
239
240             this._breakpointsByDebuggerId[breakpointId] = breakpoint;
241             breakpoint._debuggerId = breakpointId;
242             breakpoint._debuggerLocation = locations[0];
243             if (breakpoint._debuggerLocation)
244                 this._breakpointDebuggerLocationChanged(breakpoint);
245         }
246         this._debuggerModel.setBreakpointByScriptLocation(rawLocation, breakpoint.condition, didSetBreakpoint.bind(this));
247     },
248
249     /**
250      * @param {WebInspector.Breakpoint} breakpoint
251      */
252     _removeBreakpointFromDebugger: function(breakpoint)
253     {
254         if (!("_debuggerId" in breakpoint))
255             return;
256         this._debuggerModel.removeBreakpoint(breakpoint._debuggerId);
257         delete this._breakpointsByDebuggerId[breakpoint._debuggerId];
258         delete breakpoint._debuggerId;
259         delete breakpoint._debuggerLocation;
260     },
261
262     /**
263      * @param {WebInspector.Event} event
264      */
265     _breakpointResolved: function(event)
266     {
267         var breakpoint = this._breakpointsByDebuggerId[event.data["breakpointId"]];
268         breakpoint._debuggerLocation = event.data["location"];
269         this._breakpointDebuggerLocationChanged(breakpoint);
270     },
271
272     _saveBreakpoints: function()
273     {
274         var serializedBreakpoints = [];
275         /**
276          * @this {WebInspector.BreakpointManager}
277          * @param {WebInspector.Breakpoint} breakpoint
278          */
279         function serializePersistent(breakpoint)
280         {
281             if (breakpoint.persistent)
282                 serializedBreakpoints.push(breakpoint.serialize());
283         }
284         this._forEachBreakpoint(serializePersistent.bind(this));
285         this._breakpointStorage.set(serializedBreakpoints);
286     },
287
288     reset: function()
289     {
290         /**
291          * @this {WebInspector.BreakpointManager}
292          * @param {WebInspector.Breakpoint} breakpoint
293          */
294         function resetBreakpoint(breakpoint)
295         {
296             this._removeBreakpointFromDebugger(breakpoint);
297             delete breakpoint._materialized;
298         }
299         this._forEachBreakpoint(resetBreakpoint.bind(this));
300     },
301
302     debuggerReset: function()
303     {
304         /**
305          * @this {WebInspector.BreakpointManager}
306          * @param {WebInspector.Breakpoint} breakpoint
307          */
308         function resetOrDeleteBreakpoint(breakpoint)
309         {
310             if (breakpoint.persistent) {
311                 delete breakpoint.uiSourceCode;
312                 delete breakpoint._debuggerLocation;
313             } else {
314                 this._deleteBreakpointFromUI(breakpoint);
315                 delete this._breakpointsByDebuggerId[breakpoint._debuggerId];
316             }
317         }
318         this._forEachBreakpoint(resetOrDeleteBreakpoint.bind(this));
319
320         for (var id in this._breakpointsByUILocation) {
321             var empty = true;
322             for (var lineNumber in this._breakpointsByUILocation[id]) {
323                 empty = false;
324                 break;
325             }
326             if (empty)
327                 delete this._breakpointsByUILocation[id];
328         }
329     }
330 }
331
332 /**
333  * @constructor
334  * @param {string} uiSourceCodeId
335  * @param {number} lineNumber
336  * @param {string} condition
337  * @param {boolean} enabled
338  * @param {boolean} persistent
339  */
340 WebInspector.Breakpoint = function(uiSourceCodeId, lineNumber, condition, enabled, persistent)
341 {
342     this.uiSourceCodeId = uiSourceCodeId;
343     this.lineNumber = lineNumber;
344     this.condition = condition;
345     this.enabled = enabled;
346     this.persistent = persistent;
347 }
348
349 WebInspector.Breakpoint.prototype = {
350     /**
351      * @return {Object}
352      */
353     serialize: function()
354     {
355         var serializedBreakpoint = {};
356         serializedBreakpoint.sourceFileId = this.uiSourceCodeId;
357         serializedBreakpoint.lineNumber = this.lineNumber;
358         serializedBreakpoint.condition = this.condition;
359         serializedBreakpoint.enabled = this.enabled;
360         return serializedBreakpoint;
361     }
362 }
363
364 /**
365  * @param {Object} serializedBreakpoint
366  * @return {WebInspector.Breakpoint}
367  */
368 WebInspector.Breakpoint.deserialize = function(serializedBreakpoint)
369 {
370     return new WebInspector.Breakpoint(
371             serializedBreakpoint.sourceFileId,
372             serializedBreakpoint.lineNumber,
373             serializedBreakpoint.condition,
374             serializedBreakpoint.enabled,
375             true);
376 }