Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/sdk/DOMDebuggerModel.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMDebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMDebuggerModel.js |
| index a87bea1562d2bd775c539fd7617ba28029426874..3c9c69b243eab1c2ed42f17f07573d1dd7992277 100644 |
| --- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMDebuggerModel.js |
| +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMDebuggerModel.js |
| @@ -11,6 +11,14 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel { |
| this._agent = target.domdebuggerAgent(); |
| this._runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel)); |
| this._domModel = /** @type {!SDK.DOMModel} */ (target.model(SDK.DOMModel)); |
| + this._domModel.addEventListener(SDK.DOMModel.Events.DocumentUpdated, this._documentUpdated, this); |
| + this._domModel.addEventListener(SDK.DOMModel.Events.NodeRemoved, this._nodeRemoved, this); |
| + |
| + /** @type {!Array<!SDK.DOMDebuggerModel.DOMBreakpoint>} */ |
| + this._domBreakpoints = []; |
| + this._domBreakpointsSetting = Common.settings.createLocalSetting('domBreakpoints', []); |
| + if (this._domModel.existingDocument()) |
| + this._documentUpdated(); |
| } |
| /** |
| @@ -44,10 +52,244 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel { |
| } |
| return eventListeners; |
| } |
| + |
| + /** |
| + * @return {!Array<!SDK.DOMDebuggerModel.DOMBreakpoint>} |
| + */ |
| + domBreakpoints() { |
| + return this._domBreakpoints.slice(); |
| + } |
| + |
| + /** |
| + * @param {!SDK.DOMNode} node |
| + * @param {!SDK.DOMDebuggerModel.DOMBreakpoint.Type} type |
| + * @return {boolean} |
| + */ |
| + hasDOMBreakpoint(node, type) { |
| + return this._domBreakpoints.some(breakpoint => (breakpoint._node === node && breakpoint._type === type)); |
| + } |
| + |
| + /** |
| + * @param {!SDK.DOMNode} node |
| + * @param {!SDK.DOMDebuggerModel.DOMBreakpoint.Type} type |
| + * @return {!SDK.DOMDebuggerModel.DOMBreakpoint} |
| + */ |
| + setDOMBreakpoint(node, type) { |
| + for (var breakpoint of this._domBreakpoints) { |
| + if (breakpoint._node === node && breakpoint._type === type) { |
| + breakpoint.setEnabled(true); |
| + return breakpoint; |
| + } |
| + } |
| + var breakpoint = new SDK.DOMDebuggerModel.DOMBreakpoint(this, node, type, true); |
| + this._domBreakpoints.push(breakpoint); |
| + this._saveDOMBreakpoints(); |
| + this.dispatchEventToListeners(SDK.DOMDebuggerModel.Events.DOMBreakpointAdded, breakpoint); |
| + return breakpoint; |
| + } |
| + |
| + /** |
| + * @param {!SDK.DOMNode} node |
| + * @param {!SDK.DOMDebuggerModel.DOMBreakpoint.Type} type |
| + */ |
| + removeDOMBreakpoint(node, type) { |
| + this._removeDOMBreakpoints(breakpoint => breakpoint._node === node && breakpoint._type === type); |
| + } |
| + |
| + removeAllDOMBreakpoints() { |
| + this._removeDOMBreakpoints(breakpoint => true); |
| + } |
| + |
| + /** |
| + * @param {!Object} auxData |
| + * @return {?{type: !SDK.DOMDebuggerModel.DOMBreakpoint.Type, node: !SDK.DOMNode, targetNode: ?SDK.DOMNode, insertion: boolean}} |
| + */ |
| + resolveDOMBreakpointData(auxData) { |
| + var type = auxData['type']; |
| + var node = this._domModel.nodeForId(auxData['nodeId']); |
| + if (!type || !node) |
| + return null; |
| + var targetNode = null; |
| + var insertion = false; |
| + if (type === SDK.DOMDebuggerModel.DOMBreakpoint.Type.SubtreeModified) { |
| + insertion = auxData['insertion'] || false; |
| + targetNode = this._domModel.nodeForId(auxData['targetNodeId']); |
| + } |
| + return {type: type, node: node, targetNode: targetNode, insertion: insertion}; |
| + } |
| + |
| + /** |
| + * @return {string} |
| + */ |
| + _currentURL() { |
| + var domDocument = this._domModel.existingDocument(); |
| + return domDocument ? domDocument.documentURL : ''; |
| + } |
| + |
| + _documentUpdated() { |
| + var removed = this._domBreakpoints; |
| + this._domBreakpoints = []; |
| + this.dispatchEventToListeners(SDK.DOMDebuggerModel.Events.DOMBreakpointsRemoved, removed); |
| + |
| + var currentURL = this._currentURL(); |
| + for (var breakpoint of this._domBreakpointsSetting.get()) { |
| + if (breakpoint.url !== currentURL) |
| + continue; |
| + this._domModel.pushNodeByPathToFrontend(breakpoint.path, nodeId => { |
| + var node = nodeId ? this._domModel.nodeForId(nodeId) : null; |
| + if (!node) |
| + return; |
| + var domBreakpoint = new SDK.DOMDebuggerModel.DOMBreakpoint(this, node, breakpoint.type, breakpoint.enabled); |
| + this._domBreakpoints.push(domBreakpoint); |
| + this.dispatchEventToListeners(SDK.DOMDebuggerModel.Events.DOMBreakpointAdded, domBreakpoint); |
| + }); |
| + } |
| + } |
| + |
| + /** |
| + * @param {function(!SDK.DOMDebuggerModel.DOMBreakpoint):boolean} filter |
| + */ |
| + _removeDOMBreakpoints(filter) { |
| + var removed = []; |
| + var left = []; |
| + for (var breakpoint of this._domBreakpoints) { |
| + if (filter(breakpoint)) { |
| + removed.push(breakpoint); |
| + if (breakpoint._enabled) { |
| + breakpoint._enabled = false; |
| + breakpoint._disable(); |
| + } |
| + } else { |
| + left.push(breakpoint); |
| + } |
| + } |
| + |
| + if (!removed.length) |
| + return; |
| + this._domBreakpoints = left; |
| + this._saveDOMBreakpoints(); |
| + this.dispatchEventToListeners(SDK.DOMDebuggerModel.Events.DOMBreakpointsRemoved, removed); |
| + } |
| + |
| + /** |
| + * @param {!Common.Event} event |
| + */ |
| + _nodeRemoved(event) { |
| + var node = /** @type {!SDK.DOMNode} */ (event.data.node); |
| + var children = node.children() || []; |
| + this._removeDOMBreakpoints(breakpoint => breakpoint._node === node || children.indexOf(breakpoint._node) !== -1); |
| + } |
| + |
| + _saveDOMBreakpoints() { |
| + var currentURL = this._currentURL(); |
| + var breakpoints = this._domBreakpointsSetting.get().filter(breakpoint => breakpoint.url !== currentURL); |
| + for (var breakpoint of this._domBreakpoints) { |
| + breakpoints.push( |
| + {url: currentURL, path: breakpoint._node.path(), type: breakpoint._type, enabled: breakpoint._enabled}); |
| + } |
| + this._domBreakpointsSetting.set(breakpoints); |
| + } |
| }; |
| SDK.SDKModel.register(SDK.DOMDebuggerModel, SDK.Target.Capability.DOM, false); |
| +/** @enum {symbol} */ |
| +SDK.DOMDebuggerModel.Events = { |
| + DOMBreakpointAdded: Symbol('DOMBreakpointAdded'), |
| + DOMBreakpointToggled: Symbol('DOMBreakpointToggled'), |
| + DOMBreakpointsRemoved: Symbol('DOMBreakpointsRemoved'), |
| +}; |
| + |
| +SDK.DOMDebuggerModel.DOMBreakpoint = class { |
| + /** |
| + * @param {!SDK.DOMDebuggerModel} domDebuggerModel |
| + * @param {!SDK.DOMNode} node |
| + * @param {!SDK.DOMDebuggerModel.DOMBreakpoint.Type} type |
| + * @param {boolean} enabled |
| + */ |
| + constructor(domDebuggerModel, node, type, enabled) { |
|
pfeldman
2017/04/24 23:46:20
Hi Java! This could totally be a struct.
dgozman
2017/04/25 19:24:25
Done.
|
| + this._domDebuggerModel = domDebuggerModel; |
| + this._node = node; |
| + this._type = type; |
| + this._enabled = enabled; |
| + if (enabled) |
| + this._enable(); |
| + } |
| + |
| + /** |
| + * @return {!SDK.DOMDebuggerModel} |
| + */ |
| + domDebuggerModel() { |
| + return this._domDebuggerModel; |
| + } |
| + |
| + /** |
| + * @return {!SDK.DOMNode} |
| + */ |
| + node() { |
| + return this._node; |
| + } |
| + |
| + /** |
| + * @return {!SDK.DOMDebuggerModel.DOMBreakpoint.Type} |
| + */ |
| + type() { |
| + return this._type; |
| + } |
| + |
| + /** |
| + * @return {boolean} |
| + */ |
| + enabled() { |
| + return this._enabled; |
| + } |
| + |
| + /** |
| + * @param {boolean} enabled |
| + */ |
| + setEnabled(enabled) { |
| + if (enabled === this._enabled) |
| + return; |
| + |
| + this._enabled = enabled; |
| + if (enabled) |
| + this._enable(); |
| + else |
| + this._disable(); |
| + this._domDebuggerModel.dispatchEventToListeners(SDK.DOMDebuggerModel.Events.DOMBreakpointToggled, this); |
| + } |
| + |
| + _enable() { |
| + this._domDebuggerModel._agent.setDOMBreakpoint(this._node.id, this._type); |
| + this._node.setMarker(SDK.DOMDebuggerModel.DOMBreakpoint.Marker, true); |
| + } |
| + |
| + _disable() { |
| + this._domDebuggerModel._agent.removeDOMBreakpoint(this._node.id, this._type); |
| + this._node.setMarker(SDK.DOMDebuggerModel.DOMBreakpoint.Marker, this._nodeHasBreakpoints() ? true : null); |
| + } |
| + |
| + /** |
| + * @return {boolean} |
| + */ |
| + _nodeHasBreakpoints() { |
| + for (var breakpoint of this._domDebuggerModel._domBreakpoints) { |
|
pfeldman
2017/04/24 23:46:20
Move into model, retain private.
dgozman
2017/04/25 19:24:25
Done.
|
| + if (breakpoint._node === this._node && breakpoint._enabled) |
| + return true; |
| + } |
| + return false; |
| + } |
| +}; |
| + |
| +/** @typedef {Protocol.DOMDebugger.DOMBreakpointType} */ |
| +SDK.DOMDebuggerModel.DOMBreakpoint.Type = Protocol.DOMDebugger.DOMBreakpointType; |
| +// SubtreeModified: Protocol.DOMDebugger.DOMBreakpointType.SubtreeModified, |
| +// AttributeModified: Protocol.DOMDebugger.DOMBreakpointType.AttributeModified, |
| +// NodeRemoved: Protocol.DOMDebugger.DOMBreakpointType.NodeRemoved, |
| +// }; |
| + |
| +SDK.DOMDebuggerModel.DOMBreakpoint.Marker = 'breakpoint-marker'; |
| + |
| SDK.EventListener = class { |
| /** |
| * @param {!SDK.DOMDebuggerModel} domDebuggerModel |