| /* |
| * Copyright (C) 2013 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| WebInspector.Breakpoint = function(sourceCodeLocationOrInfo, disabled, condition) |
| { |
| WebInspector.Object.call(this); |
| |
| if (sourceCodeLocationOrInfo instanceof WebInspector.SourceCodeLocation) { |
| var sourceCode = sourceCodeLocationOrInfo.sourceCode; |
| var url = sourceCode ? sourceCode.url : null; |
| var scriptIdentifier = sourceCode instanceof WebInspector.Script ? sourceCode.id : null; |
| var location = sourceCodeLocationOrInfo; |
| } else if (sourceCodeLocationOrInfo && typeof sourceCodeLocationOrInfo === "object") { |
| var url = sourceCodeLocationOrInfo.url; |
| var lineNumber = sourceCodeLocationOrInfo.lineNumber || 0; |
| var columnNumber = sourceCodeLocationOrInfo.columnNumber || 0; |
| var location = new WebInspector.SourceCodeLocation(null, lineNumber, columnNumber); |
| disabled = sourceCodeLocationOrInfo.disabled; |
| condition = sourceCodeLocationOrInfo.condition; |
| } else |
| console.error("Unexpected type passed to WebInspector.Breakpoint", sourceCodeLocationOrInfo); |
| |
| this._id = null; |
| this._url = url || null; |
| this._scriptIdentifier = scriptIdentifier || null; |
| this._disabled = disabled || false; |
| this._condition = condition || ""; |
| this._resolved = false; |
| |
| this._sourceCodeLocation = location; |
| this._sourceCodeLocation.addEventListener(WebInspector.SourceCodeLocation.Event.LocationChanged, this._sourceCodeLocationLocationChanged, this); |
| this._sourceCodeLocation.addEventListener(WebInspector.SourceCodeLocation.Event.DisplayLocationChanged, this._sourceCodeLocationDisplayLocationChanged, this); |
| }; |
| |
| WebInspector.Object.addConstructorFunctions(WebInspector.Breakpoint); |
| |
| WebInspector.Breakpoint.PopoverClassName = "edit-breakpoint-popover-content"; |
| WebInspector.Breakpoint.PopoverConditionInputId = "edit-breakpoint-popover-condition"; |
| |
| WebInspector.Breakpoint.Event = { |
| DisabledStateDidChange: "breakpoint-disabled-state-did-change", |
| ResolvedStateDidChange: "breakpoint-resolved-state-did-change", |
| ConditionDidChange: "breakpoint-condition-did-change", |
| LocationDidChange: "breakpoint-location-did-change", |
| DisplayLocationDidChange: "breakpoint-display-location-did-change", |
| }; |
| |
| WebInspector.Breakpoint.prototype = { |
| constructor: WebInspector.Breakpoint, |
| |
| // Public |
| |
| get id() |
| { |
| return this._id; |
| }, |
| |
| set id(id) |
| { |
| this._id = id || null; |
| }, |
| |
| get url() |
| { |
| return this._url; |
| }, |
| |
| get scriptIdentifier() |
| { |
| return this._scriptIdentifier; |
| }, |
| |
| get sourceCodeLocation() |
| { |
| return this._sourceCodeLocation; |
| }, |
| |
| get resolved() |
| { |
| return this._resolved && WebInspector.debuggerManager.breakpointsEnabled; |
| }, |
| |
| set resolved(resolved) |
| { |
| if (this._resolved === resolved) |
| return; |
| |
| this._resolved = resolved || false; |
| |
| this.dispatchEventToListeners(WebInspector.Breakpoint.Event.ResolvedStateDidChange); |
| }, |
| |
| get disabled() |
| { |
| return this._disabled; |
| }, |
| |
| set disabled(disabled) |
| { |
| if (this._disabled === disabled) |
| return; |
| |
| this._disabled = disabled || false; |
| |
| this.dispatchEventToListeners(WebInspector.Breakpoint.Event.DisabledStateDidChange); |
| }, |
| |
| get condition() |
| { |
| return this._condition; |
| }, |
| |
| set condition(condition) |
| { |
| if (this._condition === condition) |
| return; |
| |
| this._condition = condition; |
| |
| this.dispatchEventToListeners(WebInspector.Breakpoint.Event.ConditionDidChange); |
| }, |
| |
| get info() |
| { |
| // The id, scriptIdentifier and resolved state are tied to the current session, so don't include them for serialization. |
| return { |
| url: this._url, |
| lineNumber: this._sourceCodeLocation.lineNumber, |
| columnNumber: this._sourceCodeLocation.columnNumber, |
| disabled: this._disabled, |
| condition: this._condition |
| }; |
| }, |
| |
| appendContextMenuItems: function(contextMenu, breakpointDisplayElement) |
| { |
| function editBreakpoint() |
| { |
| this._showEditBreakpointPopover(breakpointDisplayElement); |
| } |
| |
| function removeBreakpoint() |
| { |
| WebInspector.debuggerManager.removeBreakpoint(this); |
| } |
| |
| function toggleBreakpoint() |
| { |
| this.disabled = !this.disabled; |
| } |
| |
| function revealOriginalSourceCodeLocation() |
| { |
| WebInspector.resourceSidebarPanel.showOriginalOrFormattedSourceCodeLocation(this._sourceCodeLocation); |
| } |
| |
| if (WebInspector.debuggerManager.isBreakpointEditable(this)) |
| contextMenu.appendItem(WebInspector.UIString("Edit Breakpoint…"), editBreakpoint.bind(this)); |
| |
| if (this._disabled) |
| contextMenu.appendItem(WebInspector.UIString("Enable Breakpoint"), toggleBreakpoint.bind(this)); |
| else |
| contextMenu.appendItem(WebInspector.UIString("Disable Breakpoint"), toggleBreakpoint.bind(this)); |
| |
| if (WebInspector.debuggerManager.isBreakpointRemovable(this)) { |
| contextMenu.appendSeparator(); |
| contextMenu.appendItem(WebInspector.UIString("Delete Breakpoint"), removeBreakpoint.bind(this)); |
| } |
| |
| if (this._sourceCodeLocation.hasMappedLocation()) { |
| contextMenu.appendSeparator(); |
| contextMenu.appendItem(WebInspector.UIString("Reveal in Original Resource"), revealOriginalSourceCodeLocation.bind(this)); |
| } |
| }, |
| |
| // Private |
| |
| _popoverToggleCheckboxChanged: function(event) |
| { |
| this.disabled = !event.target.checked; |
| }, |
| |
| _popoverConditionInputChanged: function(event) |
| { |
| this.condition = event.target.value; |
| }, |
| |
| _popoverConditionInputKeyDown: function(event) |
| { |
| if (this._keyboardShortcutEsc.matchesEvent(event) || this._keyboardShortcutEnter.matchesEvent(event)) { |
| this._popover.dismiss(); |
| event.stopPropagation(); |
| event.preventDefault(); |
| } |
| }, |
| |
| _editBreakpointPopoverContentElement: function() |
| { |
| var content = document.createElement("div"); |
| content.className = WebInspector.Breakpoint.PopoverClassName; |
| |
| var checkboxElement = document.createElement("input"); |
| checkboxElement.type = "checkbox"; |
| checkboxElement.checked = !this._disabled; |
| checkboxElement.addEventListener("change", this._popoverToggleCheckboxChanged.bind(this)); |
| |
| var checkboxLabel = document.createElement("label"); |
| checkboxLabel.className = "toggle"; |
| checkboxLabel.appendChild(checkboxElement); |
| checkboxLabel.appendChild(document.createTextNode(this._sourceCodeLocation.displayLocationString())); |
| |
| var table = document.createElement("table"); |
| |
| var conditionRow = table.appendChild(document.createElement("tr")); |
| var conditionHeader = conditionRow.appendChild(document.createElement("th")); |
| var conditionData = conditionRow.appendChild(document.createElement("td")); |
| var conditionLabel = conditionHeader.appendChild(document.createElement("label")); |
| var conditionInput = conditionData.appendChild(document.createElement("input")); |
| conditionInput.id = WebInspector.Breakpoint.PopoverConditionInputId; |
| conditionInput.value = this._condition || ""; |
| conditionInput.spellcheck = false; |
| conditionInput.addEventListener("change", this._popoverConditionInputChanged.bind(this)); |
| conditionInput.addEventListener("keydown", this._popoverConditionInputKeyDown.bind(this)); |
| conditionInput.placeholder = WebInspector.UIString("Conditional expression"); |
| conditionLabel.setAttribute("for", conditionInput.id); |
| conditionLabel.textContent = WebInspector.UIString("Condition"); |
| |
| content.appendChild(checkboxLabel); |
| content.appendChild(table); |
| |
| return content; |
| }, |
| |
| _showEditBreakpointPopover: function(element) |
| { |
| const padding = 2; |
| var bounds = WebInspector.Rect.rectFromClientRect(element.getBoundingClientRect()); |
| bounds.origin.x -= 1; // Move the anchor left one pixel so it looks more centered. |
| bounds.origin.x -= padding; |
| bounds.origin.y -= padding; |
| bounds.size.width += padding * 2; |
| bounds.size.height += padding * 2; |
| |
| this._popover = this._popover || new WebInspector.Popover(this); |
| this._popover.content = this._editBreakpointPopoverContentElement(); |
| this._popover.present(bounds, [WebInspector.RectEdge.MAX_Y]); |
| |
| if (!this._keyboardShortcutEsc) { |
| this._keyboardShortcutEsc = new WebInspector.KeyboardShortcut(null, WebInspector.KeyboardShortcut.Key.Escape); |
| this._keyboardShortcutEnter = new WebInspector.KeyboardShortcut(null, WebInspector.KeyboardShortcut.Key.Enter); |
| } |
| |
| document.getElementById(WebInspector.Breakpoint.PopoverConditionInputId).select(); |
| }, |
| |
| _sourceCodeLocationLocationChanged: function(event) |
| { |
| this.dispatchEventToListeners(WebInspector.Breakpoint.Event.LocationDidChange, event.data); |
| }, |
| |
| _sourceCodeLocationDisplayLocationChanged: function(event) |
| { |
| this.dispatchEventToListeners(WebInspector.Breakpoint.Event.DisplayLocationDidChange, event.data); |
| } |
| }; |
| |
| WebInspector.Breakpoint.prototype.__proto__ = WebInspector.Object.prototype; |