2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
33 * @param {WebInspector.Setting} breakpointStorage
34 * @param {function(WebInspector.Breakpoint)} breakpointAddedDelegate
35 * @param {function(WebInspector.Breakpoint)} breakpointRemovedDelegate
36 * @param {WebInspector.DebuggerModel} debuggerModel
38 WebInspector.BreakpointManager = function(breakpointStorage, breakpointAddedDelegate, breakpointRemovedDelegate, debuggerModel)
40 this._breakpointStorage = breakpointStorage;
41 this._breakpointAddedDelegate = breakpointAddedDelegate;
42 this._breakpointRemovedDelegate = breakpointRemovedDelegate;
44 * @type {Object.<string, Object.<string,WebInspector.Breakpoint>>}
46 this._breakpointsByUILocation = {};
48 this._debuggerModel = debuggerModel;
51 * @type {Object.<DebuggerAgent.BreakpointId, WebInspector.Breakpoint>}
53 this._breakpointsByDebuggerId = {};
54 this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
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);
64 WebInspector.BreakpointManager.prototype = {
66 * @param {WebInspector.UISourceCode} uiSourceCode
68 uiSourceCodeAdded: function(uiSourceCode)
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);
81 * @param {WebInspector.UISourceCode} uiSourceCode
83 breakpointsForUISourceCode: function(uiSourceCode)
85 return this._breakpoints(uiSourceCode.id);
89 * @param {WebInspector.UISourceCode} uiSourceCode
90 * @param {number} lineNumber
91 * @param {string} condition
92 * @param {boolean} enabled
94 setBreakpoint: function(uiSourceCode, lineNumber, condition, enabled)
96 if (this._breakpoint(uiSourceCode.id, lineNumber))
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);
107 * @param {WebInspector.UISourceCode} uiSourceCode
108 * @param {number} lineNumber
110 removeBreakpoint: function(uiSourceCode, lineNumber)
112 var breakpoint = this._breakpoint(uiSourceCode.id, lineNumber);
115 this._deleteBreakpointFromUI(breakpoint);
116 this._removeBreakpointFromDebugger(breakpoint);
120 * @param {WebInspector.Breakpoint} breakpoint
121 * @param {WebInspector.RawSourceCode.SourceMapping} sourceMapping
122 * @param {WebInspector.UISourceCode} uiSourceCode
124 _materializeBreakpoint: function(breakpoint, sourceMapping, uiSourceCode)
126 if (!breakpoint.enabled || breakpoint._materialized)
129 breakpoint._materialized = true;
130 var rawLocation = sourceMapping.uiLocationToRawLocation(uiSourceCode, breakpoint.lineNumber, 0);
131 this._setBreakpointInDebugger(breakpoint, rawLocation);
135 * @param {WebInspector.Breakpoint} breakpoint
137 _breakpointDebuggerLocationChanged: function(breakpoint)
139 if (!breakpoint.uiSourceCode)
141 var uiLocation = breakpoint.uiSourceCode.rawSourceCode.sourceMapping.rawLocationToUILocation(breakpoint._debuggerLocation);
142 if (uiLocation.lineNumber === breakpoint.lineNumber)
145 if (!this._moveBreakpointInUI(breakpoint, uiLocation.lineNumber))
146 this._removeBreakpointFromDebugger(breakpoint);
150 * @param {WebInspector.Breakpoint} breakpoint
152 _addBreakpointToUI: function(breakpoint)
154 console.assert(!this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber));
155 this._breakpoints(breakpoint.uiSourceCodeId)[breakpoint.lineNumber] = breakpoint;
156 this._saveBreakpoints();
157 this._breakpointAddedDelegate(breakpoint);
161 * @param {WebInspector.Breakpoint} breakpoint
163 _deleteBreakpointFromUI: function(breakpoint)
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);
172 * @param {WebInspector.Breakpoint} breakpoint
173 * @param {number} lineNumber
175 _moveBreakpointInUI: function(breakpoint, lineNumber)
177 this._deleteBreakpointFromUI(breakpoint);
178 if (this._breakpoint(breakpoint.uiSourceCodeId, lineNumber))
180 breakpoint.lineNumber = lineNumber;
181 this._addBreakpointToUI(breakpoint);
186 * @param {string} uiSourceCodeId
188 _breakpoints: function(uiSourceCodeId)
190 if (!this._breakpointsByUILocation[uiSourceCodeId])
191 this._breakpointsByUILocation[uiSourceCodeId] = {};
192 return this._breakpointsByUILocation[uiSourceCodeId];
196 * @param {string} uiSourceCodeId
197 * @param {number} lineNumber
199 _breakpoint: function(uiSourceCodeId, lineNumber)
201 return this._breakpoints(uiSourceCodeId)[lineNumber];
205 * @param {function(WebInspector.Breakpoint)} handler
207 _forEachBreakpoint: function(handler)
209 for (var uiSourceCodeId in this._breakpointsByUILocation) {
210 var breakpoints = this._breakpointsByUILocation[uiSourceCodeId];
211 for (var lineNumber in breakpoints)
212 handler(breakpoints[lineNumber]);
217 * @param {WebInspector.Breakpoint} breakpoint
218 * @param {DebuggerAgent.Location} rawLocation
220 _setBreakpointInDebugger: function(breakpoint, rawLocation)
223 * @this {WebInspector.BreakpointManager}
224 * @param {DebuggerAgent.BreakpointId} breakpointId
225 * @param {Array.<DebuggerAgent.Location>} locations
227 function didSetBreakpoint(breakpointId, locations)
229 if (breakpoint === this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber)) {
231 this._deleteBreakpointFromUI(breakpoint);
236 this._debuggerModel.removeBreakpoint(breakpointId);
240 this._breakpointsByDebuggerId[breakpointId] = breakpoint;
241 breakpoint._debuggerId = breakpointId;
242 breakpoint._debuggerLocation = locations[0];
243 if (breakpoint._debuggerLocation)
244 this._breakpointDebuggerLocationChanged(breakpoint);
246 this._debuggerModel.setBreakpointByScriptLocation(rawLocation, breakpoint.condition, didSetBreakpoint.bind(this));
250 * @param {WebInspector.Breakpoint} breakpoint
252 _removeBreakpointFromDebugger: function(breakpoint)
254 if (!("_debuggerId" in breakpoint))
256 this._debuggerModel.removeBreakpoint(breakpoint._debuggerId);
257 delete this._breakpointsByDebuggerId[breakpoint._debuggerId];
258 delete breakpoint._debuggerId;
259 delete breakpoint._debuggerLocation;
263 * @param {WebInspector.Event} event
265 _breakpointResolved: function(event)
267 var breakpoint = this._breakpointsByDebuggerId[event.data["breakpointId"]];
268 breakpoint._debuggerLocation = event.data["location"];
269 this._breakpointDebuggerLocationChanged(breakpoint);
272 _saveBreakpoints: function()
274 var serializedBreakpoints = [];
276 * @this {WebInspector.BreakpointManager}
277 * @param {WebInspector.Breakpoint} breakpoint
279 function serializePersistent(breakpoint)
281 if (breakpoint.persistent)
282 serializedBreakpoints.push(breakpoint.serialize());
284 this._forEachBreakpoint(serializePersistent.bind(this));
285 this._breakpointStorage.set(serializedBreakpoints);
291 * @this {WebInspector.BreakpointManager}
292 * @param {WebInspector.Breakpoint} breakpoint
294 function resetBreakpoint(breakpoint)
296 this._removeBreakpointFromDebugger(breakpoint);
297 delete breakpoint._materialized;
299 this._forEachBreakpoint(resetBreakpoint.bind(this));
302 debuggerReset: function()
305 * @this {WebInspector.BreakpointManager}
306 * @param {WebInspector.Breakpoint} breakpoint
308 function resetOrDeleteBreakpoint(breakpoint)
310 if (breakpoint.persistent) {
311 delete breakpoint.uiSourceCode;
312 delete breakpoint._debuggerLocation;
314 this._deleteBreakpointFromUI(breakpoint);
315 delete this._breakpointsByDebuggerId[breakpoint._debuggerId];
318 this._forEachBreakpoint(resetOrDeleteBreakpoint.bind(this));
320 for (var id in this._breakpointsByUILocation) {
322 for (var lineNumber in this._breakpointsByUILocation[id]) {
327 delete this._breakpointsByUILocation[id];
334 * @param {string} uiSourceCodeId
335 * @param {number} lineNumber
336 * @param {string} condition
337 * @param {boolean} enabled
338 * @param {boolean} persistent
340 WebInspector.Breakpoint = function(uiSourceCodeId, lineNumber, condition, enabled, persistent)
342 this.uiSourceCodeId = uiSourceCodeId;
343 this.lineNumber = lineNumber;
344 this.condition = condition;
345 this.enabled = enabled;
346 this.persistent = persistent;
349 WebInspector.Breakpoint.prototype = {
353 serialize: function()
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;
365 * @param {Object} serializedBreakpoint
366 * @return {WebInspector.Breakpoint}
368 WebInspector.Breakpoint.deserialize = function(serializedBreakpoint)
370 return new WebInspector.Breakpoint(
371 serializedBreakpoint.sourceFileId,
372 serializedBreakpoint.lineNumber,
373 serializedBreakpoint.condition,
374 serializedBreakpoint.enabled,