Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/sdk/DOMBreakpointManager.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMBreakpointManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMBreakpointManager.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3908af4102ab49848d4fb5c93f9eb84b9bff5a9e |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMBreakpointManager.js |
| @@ -0,0 +1,292 @@ |
| +// Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +/** |
| + * @constructor |
| + * @extends {WebInspector.Object} |
| + * @implements {WebInspector.TargetManager.Observer} |
| + */ |
| +WebInspector.DOMBreakpointManager = function() |
| +{ |
| + /** @type {!Map<!WebInspector.Target, !Protocol.DOMDebuggerAgent>} */ |
| + this._agents = new Map(); |
| + this._domBreakpointsSetting = WebInspector.settings.createLocalSetting("domBreakpoints", []); |
| + /** @type {!Map<string, !WebInspector.DOMBreakpointManager.Breakpoint>} */ |
| + this._breakpoints = new Map(); |
| + WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.DocumentUpdated, this._restoreBreakpoints, this); |
| + WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this); |
| + WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.InspectedURLChanged, this._inspectedURLChanged, this); |
| + WebInspector.targetManager.observeTargets(this); |
| +} |
| + |
| +WebInspector.DOMBreakpointManager.Marker = "breakpoint-marker"; |
| + |
| +WebInspector.DOMBreakpointManager.Events = { |
| + BreakpointsChanged: "BreakpointsChanged" |
| +}; |
| + |
| +WebInspector.DOMBreakpointManager.prototype = { |
| + /** |
| + * @override |
| + * @param {!WebInspector.Target} target |
| + */ |
| + targetAdded: function(target) |
| + { |
| + if (target.hasDOMCapability()) |
| + this._agents.set(target, target.domdebuggerAgent()); |
| + }, |
| + |
| + /** |
| + * @override |
| + * @param {!WebInspector.Target} target |
| + */ |
| + targetRemoved: function(target) |
| + { |
| + if (target.hasDOMCapability()) |
| + this._agents.delete(target); |
| + }, |
| + |
| + /** |
| + * @return {!Map<string, !WebInspector.DOMBreakpointManager.Breakpoint>} |
|
lushnikov
2016/08/11 18:40:18
why do we return map here and not an array?
chenwilliam
2016/08/17 01:20:11
I was returning a map since that's how the class w
|
| + */ |
| + domBreakpoints: function() |
| + { |
| + return this._breakpoints; |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.DOMNode} node |
| + * @param {!DOMDebuggerAgent.DOMBreakpointType} type |
| + * @param {boolean} enabled |
| + */ |
| + setBreakpoint: function(node, type, enabled) |
| + { |
| + this._innerSetBreakpoint(node, type, enabled); |
| + this._saveBreakpoints(); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.DOMNode} node |
| + * @param {!DOMDebuggerAgent.DOMBreakpointType} type |
| + * @param {boolean} enabled |
| + */ |
| + _innerSetBreakpoint: function(node, type, enabled) |
| + { |
| + var breakpoint = new WebInspector.DOMBreakpointManager.Breakpoint(node, type, this._inspectedURL, enabled); |
|
lushnikov
2016/08/11 18:40:18
instead of using inspectedURL, we probably should
chenwilliam
2016/08/17 01:20:11
Done.
|
| + this._breakpoints.set(this._breakpointId(node, type), breakpoint); |
| + var agent = this._agents.get(node.target()); |
| + if (enabled) { |
| + agent.setDOMBreakpoint(node.id, type); |
| + node.setMarker(WebInspector.DOMBreakpointManager.Marker, true); |
| + } else { |
| + agent.removeDOMBreakpoint(node.id, type); |
| + node.setMarker(WebInspector.DOMBreakpointManager.Marker, this._hasOtherBreakpoints(node, type) ? true : null); |
| + } |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.DOMNode} node |
| + * @param {!DOMDebuggerAgent.DOMBreakpointType} type |
| + */ |
| + removeBreakpoint: function(node, type) |
| + { |
| + this._innerRemoveBreakpoint(node, type); |
| + this._saveBreakpoints(); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.DOMNode} node |
| + * @param {!DOMDebuggerAgent.DOMBreakpointType} type |
| + */ |
| + _innerRemoveBreakpoint: function(node, type) |
| + { |
| + var breakpointId = this._breakpointId(node, type); |
| + var breakpoint = this._breakpoints.get(breakpointId); |
| + if (breakpoint.enabled) { |
| + var agent = this._agents.get(node.target()); |
| + agent.removeDOMBreakpoint(node.id, type); |
| + node.setMarker(WebInspector.DOMBreakpointManager.Marker, this._hasOtherBreakpoints(node, type) ? true : null); |
| + } |
| + this._breakpoints.remove(breakpointId); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.DOMNode} node |
| + * @param {!DOMDebuggerAgent.DOMBreakpointType} type |
| + */ |
| + toggleBreakpoint: function(node, type) |
| + { |
| + var nodeBreakpoints = this.nodeBreakpoints(node); |
| + if (!nodeBreakpoints[type]) |
| + this.setBreakpoint(node, type, true); |
| + else |
| + this.removeBreakpoint(node, type); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.DOMNode} node |
| + */ |
| + removeBreakpointsForNode: function(node) |
|
lushnikov
2016/08/11 18:40:19
why is this part of public API? AFAIU It's not use
chenwilliam
2016/08/17 01:20:11
Done.
|
| + { |
| + for (var breakpoint of this._breakpoints.values()) { |
| + if (breakpoint.node === node) |
| + this._innerRemoveBreakpoint(breakpoint.node, breakpoint.type); |
| + } |
| + this._saveBreakpoints(); |
| + }, |
| + |
| + removeAllBreakpoints: function() |
| + { |
| + for (var breakpoint of this._breakpoints.values()) |
| + this._innerRemoveBreakpoint(breakpoint.node, breakpoint.type); |
| + this._saveBreakpoints(); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.DOMNode} node |
| + * @return {!Object<string, boolean>} |
|
lushnikov
2016/08/11 18:40:19
return Map<string, boolean>
chenwilliam
2016/08/17 01:20:11
Done.
|
| + */ |
| + nodeBreakpoints: function(node) |
| + { |
| + var nodeBreakpoints = {}; |
| + for (var breakpoint of this._breakpoints.values()) { |
| + if (breakpoint.node === node && breakpoint.enabled) |
| + nodeBreakpoints[breakpoint.type] = true; |
| + } |
| + return nodeBreakpoints; |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Event} event |
| + */ |
| + _restoreBreakpoints: function(event) |
| + { |
| + var domModel = /** @type {!WebInspector.DOMModel} */ (event.target); |
| + var pathToBreakpoints = {}; |
| + this._breakpoints = new Map(); |
|
lushnikov
2016/08/11 18:40:19
this._breakpoints.clear(); to play nice with closu
chenwilliam
2016/08/17 01:20:11
Done.
|
| + |
| + /** |
| + * @param {string} path |
| + * @param {?DOMAgent.NodeId} nodeId |
| + * @this {WebInspector.DOMBreakpointManager} |
| + */ |
| + function didPushNodeByPathToFrontend(path, nodeId) |
| + { |
| + var node = nodeId ? domModel.nodeForId(nodeId) : null; |
| + if (!node) |
| + return; |
| + |
| + for (var breakpoint of pathToBreakpoints[path]) |
| + this._innerSetBreakpoint(node, breakpoint.type, breakpoint.enabled); |
| + this.dispatchEventToListeners(WebInspector.DOMBreakpointManager.Events.BreakpointsChanged); |
| + } |
| + |
| + var breakpoints = this._domBreakpointsSetting.get(); |
| + for (var breakpoint of breakpoints) { |
| + if (breakpoint.url !== this._inspectedURL) |
| + continue; |
| + var path = breakpoint.path; |
| + if (!pathToBreakpoints[path]) { |
| + pathToBreakpoints[path] = []; |
| + domModel.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path)); |
| + } |
| + pathToBreakpoints[path].push(breakpoint); |
| + } |
| + }, |
| + |
| + _saveBreakpoints: function() |
| + { |
| + var breakpoints = []; |
| + var storedBreakpoints = this._domBreakpointsSetting.get(); |
| + for (var breakpoint of storedBreakpoints) { |
| + if (breakpoint.url !== this._inspectedURL) |
| + breakpoints.push(breakpoint); |
| + } |
| + for (var breakpoint of this._breakpoints.values()) { |
| + breakpoints.push({ |
| + url: this._inspectedURL, |
| + path: breakpoint.node.path(), |
| + type: breakpoint.type, |
| + enabled: breakpoint.enabled |
| + }); |
| + } |
| + this._domBreakpointsSetting.set(breakpoints); |
| + this.dispatchEventToListeners(WebInspector.DOMBreakpointManager.Events.BreakpointsChanged); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.DOMNode} node |
| + * @param {!DOMDebuggerAgent.DOMBreakpointType} type |
| + * @return {boolean} |
| + */ |
| + _hasOtherBreakpoints: function(node, type) |
| + { |
| + for (var breakpoint of this._breakpoints.values()) { |
| + if (breakpoint.node === node && breakpoint.type !== type && breakpoint.enabled) |
| + return true; |
| + } |
| + return false; |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Event} event |
| + */ |
| + _nodeRemoved: function(event) |
| + { |
| + var node = event.data.node; |
| + this.removeBreakpointsForNode(node); |
| + var children = node.children(); |
| + if (!children) |
| + return; |
| + for (var child of children) |
| + this.removeBreakpointsForNode(child); |
| + this._saveBreakpoints(); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Event} event |
| + */ |
| + _inspectedURLChanged: function(event) |
| + { |
| + var target = /** @type {!WebInspector.Target} */ (event.data); |
|
lushnikov
2016/08/11 18:40:18
why listen to this event altogether? it appears it
chenwilliam
2016/08/17 01:20:11
Done.
|
| + if (target !== WebInspector.targetManager.mainTarget()) |
| + return; |
| + this._inspectedURL = target.inspectedURL().removeURLFragment(); |
| + this._breakpoints = new Map(); |
| + this.dispatchEventToListeners(WebInspector.DOMBreakpointManager.Events.BreakpointsChanged); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.DOMNode} node |
| + * @param {!DOMDebuggerAgent.DOMBreakpointType} type |
| + * @return {string} |
| + */ |
| + _breakpointId: function(node, type) |
| + { |
| + return `${node.id}__${type}`; |
|
lushnikov
2016/08/11 18:40:19
let's be consistent and separate with colon
chenwilliam
2016/08/17 01:20:11
Done.
|
| + }, |
| + |
| + __proto__: WebInspector.Object.prototype |
| +}; |
| + |
| +/** |
| + * @constructor |
| + * @param {!WebInspector.DOMNode} node |
| + * @param {!DOMDebuggerAgent.DOMBreakpointType} type |
| + * @param {string} url |
| + * @param {boolean} enabled |
| + */ |
| +WebInspector.DOMBreakpointManager.Breakpoint = function(node, type, url, enabled) |
| +{ |
| + this.node = node; |
| + this.path = node.path(); |
| + this.type = type; |
| + this.url = url; |
| + this.enabled = enabled; |
| +} |
| + |
| +/** |
| + * @type {!WebInspector.DOMBreakpointManager} |
| + */ |
| +WebInspector.domBreakpointManager; |