Home | History | Annotate | Download | only in front_end
      1 /*
      2  * Copyright (C) 2008 Apple 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
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 /**
     27  * @constructor
     28  * @param {!WebInspector.BreakpointManager} breakpointManager
     29  * @extends {WebInspector.SidebarPane}
     30  */
     31 WebInspector.JavaScriptBreakpointsSidebarPane = function(breakpointManager, showSourceLineDelegate)
     32 {
     33     WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints"));
     34     this.registerRequiredCSS("breakpointsList.css");
     35 
     36     this._breakpointManager = breakpointManager;
     37     this._showSourceLineDelegate = showSourceLineDelegate;
     38 
     39     this.listElement = document.createElement("ol");
     40     this.listElement.className = "breakpoint-list";
     41 
     42     this.emptyElement = document.createElement("div");
     43     this.emptyElement.className = "info";
     44     this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");
     45 
     46     this.bodyElement.appendChild(this.emptyElement);
     47 
     48     this._items = new Map();
     49 
     50     var breakpointLocations = this._breakpointManager.allBreakpointLocations();
     51     for (var i = 0; i < breakpointLocations.length; ++i)
     52         this._addBreakpoint(breakpointLocations[i].breakpoint, breakpointLocations[i].uiLocation);
     53 
     54     this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
     55     this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);
     56 
     57     this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), true);
     58 }
     59 
     60 WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {
     61     _emptyElementContextMenu: function(event)
     62     {
     63         var contextMenu = new WebInspector.ContextMenu(event);
     64         var breakpointActive = WebInspector.debuggerModel.breakpointsActive();
     65         var breakpointActiveTitle = breakpointActive ?
     66             WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Deactivate breakpoints" : "Deactivate Breakpoints") :
     67             WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Activate breakpoints" : "Activate Breakpoints");
     68         contextMenu.appendItem(breakpointActiveTitle, WebInspector.debuggerModel.setBreakpointsActive.bind(WebInspector.debuggerModel, !breakpointActive));
     69         contextMenu.show();
     70     },
     71 
     72     /**
     73      * @param {!WebInspector.Event} event
     74      */
     75     _breakpointAdded: function(event)
     76     {
     77         this._breakpointRemoved(event);
     78 
     79         var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
     80         var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocation);
     81         this._addBreakpoint(breakpoint, uiLocation);
     82     },
     83 
     84     /**
     85      * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
     86      * @param {!WebInspector.UILocation} uiLocation
     87      */
     88     _addBreakpoint: function(breakpoint, uiLocation)
     89     {
     90         var element = document.createElement("li");
     91         element.classList.add("cursor-pointer");
     92         element.addEventListener("contextmenu", this._breakpointContextMenu.bind(this, breakpoint), true);
     93         element.addEventListener("click", this._breakpointClicked.bind(this, uiLocation), false);
     94 
     95         var checkbox = document.createElement("input");
     96         checkbox.className = "checkbox-elem";
     97         checkbox.type = "checkbox";
     98         checkbox.checked = breakpoint.enabled();
     99         checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, breakpoint), false);
    100         element.appendChild(checkbox);
    101 
    102         var labelElement = document.createTextNode(uiLocation.linkText());
    103         element.appendChild(labelElement);
    104 
    105         var snippetElement = document.createElement("div");
    106         snippetElement.className = "source-text monospace";
    107         element.appendChild(snippetElement);
    108 
    109         /**
    110          * @param {?string} content
    111          */
    112         function didRequestContent(content)
    113         {
    114             var lineEndings = content.lineEndings();
    115             if (uiLocation.lineNumber < lineEndings.length)
    116                 snippetElement.textContent = content.substring(lineEndings[uiLocation.lineNumber - 1], lineEndings[uiLocation.lineNumber]);
    117         }
    118         uiLocation.uiSourceCode.requestContent(didRequestContent.bind(this));
    119 
    120         element._data = uiLocation;
    121         var currentElement = this.listElement.firstChild;
    122         while (currentElement) {
    123             if (currentElement._data && this._compareBreakpoints(currentElement._data, element._data) > 0)
    124                 break;
    125             currentElement = currentElement.nextSibling;
    126         }
    127         this._addListElement(element, currentElement);
    128 
    129         var breakpointItem = {};
    130         breakpointItem.element = element;
    131         breakpointItem.checkbox = checkbox;
    132         this._items.put(breakpoint, breakpointItem);
    133 
    134         this.expand();
    135     },
    136 
    137     /**
    138      * @param {!WebInspector.Event} event
    139      */
    140     _breakpointRemoved: function(event)
    141     {
    142         var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
    143         var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocation);
    144         var breakpointItem = this._items.get(breakpoint);
    145         if (!breakpointItem)
    146             return;
    147         this._items.remove(breakpoint);
    148         this._removeListElement(breakpointItem.element);
    149     },
    150 
    151     /**
    152      * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
    153      */
    154     highlightBreakpoint: function(breakpoint)
    155     {
    156         var breakpointItem = this._items.get(breakpoint);
    157         if (!breakpointItem)
    158             return;
    159         breakpointItem.element.classList.add("breakpoint-hit");
    160         this._highlightedBreakpointItem = breakpointItem;
    161     },
    162 
    163     clearBreakpointHighlight: function()
    164     {
    165         if (this._highlightedBreakpointItem) {
    166             this._highlightedBreakpointItem.element.classList.remove("breakpoint-hit");
    167             delete this._highlightedBreakpointItem;
    168         }
    169     },
    170 
    171     _breakpointClicked: function(uiLocation, event)
    172     {
    173         this._showSourceLineDelegate(uiLocation.uiSourceCode, uiLocation.lineNumber);
    174     },
    175 
    176     /**
    177      * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
    178      */
    179     _breakpointCheckboxClicked: function(breakpoint, event)
    180     {
    181         // Breakpoint element has it's own click handler.
    182         event.consume();
    183         breakpoint.setEnabled(event.target.checked);
    184     },
    185 
    186     /**
    187      * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
    188      */
    189     _breakpointContextMenu: function(breakpoint, event)
    190     {
    191         var breakpoints = this._items.values();
    192         var contextMenu = new WebInspector.ContextMenu(event);
    193         contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), breakpoint.remove.bind(breakpoint));
    194         if (breakpoints.length > 1) {
    195             var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all breakpoints" : "Remove All Breakpoints");
    196             contextMenu.appendItem(removeAllTitle, this._breakpointManager.removeAllBreakpoints.bind(this._breakpointManager));
    197         }
    198 
    199         contextMenu.appendSeparator();
    200         var breakpointActive = WebInspector.debuggerModel.breakpointsActive();
    201         var breakpointActiveTitle = breakpointActive ?
    202             WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Deactivate breakpoints" : "Deactivate Breakpoints") :
    203             WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Activate breakpoints" : "Activate Breakpoints");
    204         contextMenu.appendItem(breakpointActiveTitle, WebInspector.debuggerModel.setBreakpointsActive.bind(WebInspector.debuggerModel, !breakpointActive));
    205 
    206         function enabledBreakpointCount(breakpoints)
    207         {
    208             var count = 0;
    209             for (var i = 0; i < breakpoints.length; ++i) {
    210                 if (breakpoints[i].checkbox.checked)
    211                     count++;
    212             }
    213             return count;
    214         }
    215         if (breakpoints.length > 1) {
    216             var enableBreakpointCount = enabledBreakpointCount(breakpoints);
    217             var enableTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Enable all breakpoints" : "Enable All Breakpoints");
    218             var disableTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Disable all breakpoints" : "Disable All Breakpoints");
    219 
    220             contextMenu.appendSeparator();
    221 
    222             contextMenu.appendItem(enableTitle, this._breakpointManager.toggleAllBreakpoints.bind(this._breakpointManager, true), !(enableBreakpointCount != breakpoints.length));
    223             contextMenu.appendItem(disableTitle, this._breakpointManager.toggleAllBreakpoints.bind(this._breakpointManager, false), !(enableBreakpointCount > 1));
    224         }
    225 
    226         contextMenu.show();
    227     },
    228 
    229     _addListElement: function(element, beforeElement)
    230     {
    231         if (beforeElement)
    232             this.listElement.insertBefore(element, beforeElement);
    233         else {
    234             if (!this.listElement.firstChild) {
    235                 this.bodyElement.removeChild(this.emptyElement);
    236                 this.bodyElement.appendChild(this.listElement);
    237             }
    238             this.listElement.appendChild(element);
    239         }
    240     },
    241 
    242     _removeListElement: function(element)
    243     {
    244         this.listElement.removeChild(element);
    245         if (!this.listElement.firstChild) {
    246             this.bodyElement.removeChild(this.listElement);
    247             this.bodyElement.appendChild(this.emptyElement);
    248         }
    249     },
    250 
    251     _compare: function(x, y)
    252     {
    253         if (x !== y)
    254             return x < y ? -1 : 1;
    255         return 0;
    256     },
    257 
    258     _compareBreakpoints: function(b1, b2)
    259     {
    260         return this._compare(b1.uiSourceCode.originURL(), b2.uiSourceCode.originURL()) || this._compare(b1.lineNumber, b2.lineNumber);
    261     },
    262 
    263     reset: function()
    264     {
    265         this.listElement.removeChildren();
    266         if (this.listElement.parentElement) {
    267             this.bodyElement.removeChild(this.listElement);
    268             this.bodyElement.appendChild(this.emptyElement);
    269         }
    270         this._items.clear();
    271     },
    272 
    273     __proto__: WebInspector.SidebarPane.prototype
    274 }
    275 
    276 /**
    277  * @constructor
    278  * @extends {WebInspector.NativeBreakpointsSidebarPane}
    279  */
    280 WebInspector.XHRBreakpointsSidebarPane = function()
    281 {
    282     WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("XHR Breakpoints"));
    283 
    284     this._breakpointElements = {};
    285 
    286     var addButton = document.createElement("button");
    287     addButton.className = "pane-title-button add";
    288     addButton.addEventListener("click", this._addButtonClicked.bind(this), false);
    289     addButton.title = WebInspector.UIString("Add XHR breakpoint");
    290     this.titleElement.appendChild(addButton);
    291 
    292     this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), true);
    293 
    294     this._restoreBreakpoints();
    295 }
    296 
    297 WebInspector.XHRBreakpointsSidebarPane.prototype = {
    298     _emptyElementContextMenu: function(event)
    299     {
    300         var contextMenu = new WebInspector.ContextMenu(event);
    301         contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._addButtonClicked.bind(this));
    302         contextMenu.show();
    303     },
    304 
    305     _addButtonClicked: function(event)
    306     {
    307         if (event)
    308             event.consume();
    309 
    310         this.expand();
    311 
    312         var inputElementContainer = document.createElement("p");
    313         inputElementContainer.className = "breakpoint-condition";
    314         var inputElement = document.createElement("span");
    315         inputElementContainer.textContent = WebInspector.UIString("Break when URL contains:");
    316         inputElement.className = "editing";
    317         inputElement.id = "breakpoint-condition-input";
    318         inputElementContainer.appendChild(inputElement);
    319         this._addListElement(inputElementContainer, this.listElement.firstChild);
    320 
    321         /**
    322          * @param {boolean} accept
    323          * @param {!Element} e
    324          * @param {string} text
    325          * @this {WebInspector.XHRBreakpointsSidebarPane}
    326          */
    327         function finishEditing(accept, e, text)
    328         {
    329             this._removeListElement(inputElementContainer);
    330             if (accept) {
    331                 this._setBreakpoint(text, true);
    332                 this._saveBreakpoints();
    333             }
    334         }
    335 
    336         var config = new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false));
    337         WebInspector.startEditing(inputElement, config);
    338     },
    339 
    340     _setBreakpoint: function(url, enabled)
    341     {
    342         if (url in this._breakpointElements)
    343             return;
    344 
    345         var element = document.createElement("li");
    346         element._url = url;
    347         element.addEventListener("contextmenu", this._contextMenu.bind(this, url), true);
    348 
    349         var checkboxElement = document.createElement("input");
    350         checkboxElement.className = "checkbox-elem";
    351         checkboxElement.type = "checkbox";
    352         checkboxElement.checked = enabled;
    353         checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, url), false);
    354         element._checkboxElement = checkboxElement;
    355         element.appendChild(checkboxElement);
    356 
    357         var labelElement = document.createElement("span");
    358         if (!url)
    359             labelElement.textContent = WebInspector.UIString("Any XHR");
    360         else
    361             labelElement.textContent = WebInspector.UIString("URL contains \"%s\"", url);
    362         labelElement.classList.add("cursor-auto");
    363         labelElement.addEventListener("dblclick", this._labelClicked.bind(this, url), false);
    364         element.appendChild(labelElement);
    365 
    366         var currentElement = this.listElement.firstChild;
    367         while (currentElement) {
    368             if (currentElement._url && currentElement._url < element._url)
    369                 break;
    370             currentElement = currentElement.nextSibling;
    371         }
    372         this._addListElement(element, currentElement);
    373         this._breakpointElements[url] = element;
    374         if (enabled)
    375             DOMDebuggerAgent.setXHRBreakpoint(url);
    376     },
    377 
    378     _removeBreakpoint: function(url)
    379     {
    380         var element = this._breakpointElements[url];
    381         if (!element)
    382             return;
    383 
    384         this._removeListElement(element);
    385         delete this._breakpointElements[url];
    386         if (element._checkboxElement.checked)
    387             DOMDebuggerAgent.removeXHRBreakpoint(url);
    388     },
    389 
    390     _contextMenu: function(url, event)
    391     {
    392         var contextMenu = new WebInspector.ContextMenu(event);
    393 
    394         /**
    395          * @this {WebInspector.XHRBreakpointsSidebarPane}
    396          */
    397         function removeBreakpoint()
    398         {
    399             this._removeBreakpoint(url);
    400             this._saveBreakpoints();
    401         }
    402 
    403         /**
    404          * @this {WebInspector.XHRBreakpointsSidebarPane}
    405          */
    406         function removeAllBreakpoints()
    407         {
    408             for (var url in this._breakpointElements)
    409                 this._removeBreakpoint(url);
    410             this._saveBreakpoints();
    411         }
    412         var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all breakpoints" : "Remove All Breakpoints");
    413 
    414         contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._addButtonClicked.bind(this));
    415         contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), removeBreakpoint.bind(this));
    416         contextMenu.appendItem(removeAllTitle, removeAllBreakpoints.bind(this));
    417         contextMenu.show();
    418     },
    419 
    420     _checkboxClicked: function(url, event)
    421     {
    422         if (event.target.checked)
    423             DOMDebuggerAgent.setXHRBreakpoint(url);
    424         else
    425             DOMDebuggerAgent.removeXHRBreakpoint(url);
    426         this._saveBreakpoints();
    427     },
    428 
    429     _labelClicked: function(url)
    430     {
    431         var element = this._breakpointElements[url];
    432         var inputElement = document.createElement("span");
    433         inputElement.className = "breakpoint-condition editing";
    434         inputElement.textContent = url;
    435         this.listElement.insertBefore(inputElement, element);
    436         element.classList.add("hidden");
    437 
    438         /**
    439          * @param {boolean} accept
    440          * @param {!Element} e
    441          * @param {string} text
    442          * @this {WebInspector.XHRBreakpointsSidebarPane}
    443          */
    444         function finishEditing(accept, e, text)
    445         {
    446             this._removeListElement(inputElement);
    447             if (accept) {
    448                 this._removeBreakpoint(url);
    449                 this._setBreakpoint(text, element._checkboxElement.checked);
    450                 this._saveBreakpoints();
    451             } else
    452                 element.classList.remove("hidden");
    453         }
    454 
    455         WebInspector.startEditing(inputElement, new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false)));
    456     },
    457 
    458     highlightBreakpoint: function(url)
    459     {
    460         var element = this._breakpointElements[url];
    461         if (!element)
    462             return;
    463         this.expand();
    464         element.classList.add("breakpoint-hit");
    465         this._highlightedElement = element;
    466     },
    467 
    468     clearBreakpointHighlight: function()
    469     {
    470         if (this._highlightedElement) {
    471             this._highlightedElement.classList.remove("breakpoint-hit");
    472             delete this._highlightedElement;
    473         }
    474     },
    475 
    476     _saveBreakpoints: function()
    477     {
    478         var breakpoints = [];
    479         for (var url in this._breakpointElements)
    480             breakpoints.push({ url: url, enabled: this._breakpointElements[url]._checkboxElement.checked });
    481         WebInspector.settings.xhrBreakpoints.set(breakpoints);
    482     },
    483 
    484     _restoreBreakpoints: function()
    485     {
    486         var breakpoints = WebInspector.settings.xhrBreakpoints.get();
    487         for (var i = 0; i < breakpoints.length; ++i) {
    488             var breakpoint = breakpoints[i];
    489             if (breakpoint && typeof breakpoint.url === "string")
    490                 this._setBreakpoint(breakpoint.url, breakpoint.enabled);
    491         }
    492     },
    493 
    494     __proto__: WebInspector.NativeBreakpointsSidebarPane.prototype
    495 }
    496 
    497 /**
    498  * @constructor
    499  * @extends {WebInspector.SidebarPane}
    500  */
    501 WebInspector.EventListenerBreakpointsSidebarPane = function()
    502 {
    503     WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Breakpoints"));
    504     this.registerRequiredCSS("breakpointsList.css");
    505 
    506     this.categoriesElement = document.createElement("ol");
    507     this.categoriesElement.tabIndex = 0;
    508     this.categoriesElement.classList.add("properties-tree");
    509     this.categoriesElement.classList.add("event-listener-breakpoints");
    510     this.categoriesTreeOutline = new TreeOutline(this.categoriesElement);
    511     this.bodyElement.appendChild(this.categoriesElement);
    512 
    513     this._breakpointItems = {};
    514     // FIXME: uncomment following once inspector stops being drop targer in major ports.
    515     // Otherwise, inspector page reacts on drop event and tries to load the event data.
    516     // this._createCategory(WebInspector.UIString("Drag"), true, ["drag", "drop", "dragstart", "dragend", "dragenter", "dragleave", "dragover"]);
    517     this._createCategory(WebInspector.UIString("Animation"), false, ["requestAnimationFrame", "cancelAnimationFrame", "animationFrameFired"]);
    518     this._createCategory(WebInspector.UIString("Control"), true, ["resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"]);
    519     this._createCategory(WebInspector.UIString("Clipboard"), true, ["copy", "cut", "paste", "beforecopy", "beforecut", "beforepaste"]);
    520     this._createCategory(WebInspector.UIString("DOM Mutation"), true, ["DOMActivate", "DOMFocusIn", "DOMFocusOut", "DOMAttrModified", "DOMCharacterDataModified", "DOMNodeInserted", "DOMNodeInsertedIntoDocument", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMSubtreeModified", "DOMContentLoaded"]);
    521     this._createCategory(WebInspector.UIString("Device"), true, ["deviceorientation", "devicemotion"]);
    522     this._createCategory(WebInspector.UIString("Keyboard"), true, ["keydown", "keyup", "keypress", "input"]);
    523     this._createCategory(WebInspector.UIString("Load"), true, ["load", "beforeunload", "unload", "abort", "error", "hashchange", "popstate"]);
    524     this._createCategory(WebInspector.UIString("Mouse"), true, ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel"]);
    525     this._createCategory(WebInspector.UIString("Timer"), false, ["setTimer", "clearTimer", "timerFired"]);
    526     this._createCategory(WebInspector.UIString("Touch"), true, ["touchstart", "touchmove", "touchend", "touchcancel"]);
    527     this._createCategory(WebInspector.UIString("WebGL"), false, ["webglErrorFired", "webglWarningFired"]);
    528 
    529     this._restoreBreakpoints();
    530 }
    531 
    532 WebInspector.EventListenerBreakpointsSidebarPane.categotyListener = "listener:";
    533 WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation = "instrumentation:";
    534 
    535 /**
    536  * @param {string} eventName
    537  * @param {!Object=} auxData
    538  * @return {string}
    539  */
    540 WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI = function(eventName, auxData)
    541 {
    542     if (!WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI) {
    543         WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI = {
    544             "instrumentation:setTimer": WebInspector.UIString("Set Timer"),
    545             "instrumentation:clearTimer": WebInspector.UIString("Clear Timer"),
    546             "instrumentation:timerFired": WebInspector.UIString("Timer Fired"),
    547             "instrumentation:requestAnimationFrame": WebInspector.UIString("Request Animation Frame"),
    548             "instrumentation:cancelAnimationFrame": WebInspector.UIString("Cancel Animation Frame"),
    549             "instrumentation:animationFrameFired": WebInspector.UIString("Animation Frame Fired"),
    550             "instrumentation:webglErrorFired": WebInspector.UIString("WebGL Error Fired"),
    551             "instrumentation:webglWarningFired": WebInspector.UIString("WebGL Warning Fired")
    552         };
    553     }
    554     if (auxData) {
    555         if (eventName === "instrumentation:webglErrorFired" && auxData["webglErrorName"]) {
    556             var errorName = auxData["webglErrorName"];
    557             // If there is a hex code of the error, display only this.
    558             errorName = errorName.replace(/^.*(0x[0-9a-f]+).*$/i, "$1");
    559             return WebInspector.UIString("WebGL Error Fired (%s)", errorName);
    560         }
    561     }
    562     return WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI[eventName] || eventName.substring(eventName.indexOf(":") + 1);
    563 }
    564 
    565 WebInspector.EventListenerBreakpointsSidebarPane.prototype = {
    566     _createCategory: function(name, isDOMEvent, eventNames)
    567     {
    568         var categoryItem = {};
    569         categoryItem.element = new TreeElement(name);
    570         this.categoriesTreeOutline.appendChild(categoryItem.element);
    571         categoryItem.element.listItemElement.classList.add("event-category");
    572         categoryItem.element.selectable = true;
    573 
    574         categoryItem.checkbox = this._createCheckbox(categoryItem.element);
    575         categoryItem.checkbox.addEventListener("click", this._categoryCheckboxClicked.bind(this, categoryItem), true);
    576 
    577         categoryItem.children = {};
    578         for (var i = 0; i < eventNames.length; ++i) {
    579             var eventName = (isDOMEvent ? WebInspector.EventListenerBreakpointsSidebarPane.categotyListener :  WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation) + eventNames[i];
    580 
    581             var breakpointItem = {};
    582             var title = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName);
    583             breakpointItem.element = new TreeElement(title);
    584             categoryItem.element.appendChild(breakpointItem.element);
    585             var hitMarker = document.createElement("div");
    586             hitMarker.className = "breakpoint-hit-marker";
    587             breakpointItem.element.listItemElement.appendChild(hitMarker);
    588             breakpointItem.element.listItemElement.classList.add("source-code");
    589             breakpointItem.element.selectable = false;
    590 
    591             breakpointItem.checkbox = this._createCheckbox(breakpointItem.element);
    592             breakpointItem.checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, eventName), true);
    593             breakpointItem.parent = categoryItem;
    594 
    595             this._breakpointItems[eventName] = breakpointItem;
    596             categoryItem.children[eventName] = breakpointItem;
    597         }
    598     },
    599 
    600     _createCheckbox: function(treeElement)
    601     {
    602         var checkbox = document.createElement("input");
    603         checkbox.className = "checkbox-elem";
    604         checkbox.type = "checkbox";
    605         treeElement.listItemElement.insertBefore(checkbox, treeElement.listItemElement.firstChild);
    606         return checkbox;
    607     },
    608 
    609     _categoryCheckboxClicked: function(categoryItem)
    610     {
    611         var checked = categoryItem.checkbox.checked;
    612         for (var eventName in categoryItem.children) {
    613             var breakpointItem = categoryItem.children[eventName];
    614             if (breakpointItem.checkbox.checked === checked)
    615                 continue;
    616             if (checked)
    617                 this._setBreakpoint(eventName);
    618             else
    619                 this._removeBreakpoint(eventName);
    620         }
    621         this._saveBreakpoints();
    622     },
    623 
    624     _breakpointCheckboxClicked: function(eventName, event)
    625     {
    626         if (event.target.checked)
    627             this._setBreakpoint(eventName);
    628         else
    629             this._removeBreakpoint(eventName);
    630         this._saveBreakpoints();
    631     },
    632 
    633     _setBreakpoint: function(eventName)
    634     {
    635         var breakpointItem = this._breakpointItems[eventName];
    636         if (!breakpointItem)
    637             return;
    638         breakpointItem.checkbox.checked = true;
    639         if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener))
    640             DOMDebuggerAgent.setEventListenerBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener.length));
    641         else if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation))
    642             DOMDebuggerAgent.setInstrumentationBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation.length));
    643         this._updateCategoryCheckbox(breakpointItem.parent);
    644     },
    645 
    646     _removeBreakpoint: function(eventName)
    647     {
    648         var breakpointItem = this._breakpointItems[eventName];
    649         if (!breakpointItem)
    650             return;
    651         breakpointItem.checkbox.checked = false;
    652         if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener))
    653             DOMDebuggerAgent.removeEventListenerBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener.length));
    654         else if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation))
    655             DOMDebuggerAgent.removeInstrumentationBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation.length));
    656         this._updateCategoryCheckbox(breakpointItem.parent);
    657     },
    658 
    659     _updateCategoryCheckbox: function(categoryItem)
    660     {
    661         var hasEnabled = false, hasDisabled = false;
    662         for (var eventName in categoryItem.children) {
    663             var breakpointItem = categoryItem.children[eventName];
    664             if (breakpointItem.checkbox.checked)
    665                 hasEnabled = true;
    666             else
    667                 hasDisabled = true;
    668         }
    669         categoryItem.checkbox.checked = hasEnabled;
    670         categoryItem.checkbox.indeterminate = hasEnabled && hasDisabled;
    671     },
    672 
    673     highlightBreakpoint: function(eventName)
    674     {
    675         var breakpointItem = this._breakpointItems[eventName];
    676         if (!breakpointItem)
    677             return;
    678         this.expand();
    679         breakpointItem.parent.element.expand();
    680         breakpointItem.element.listItemElement.classList.add("breakpoint-hit");
    681         this._highlightedElement = breakpointItem.element.listItemElement;
    682     },
    683 
    684     clearBreakpointHighlight: function()
    685     {
    686         if (this._highlightedElement) {
    687             this._highlightedElement.classList.remove("breakpoint-hit");
    688             delete this._highlightedElement;
    689         }
    690     },
    691 
    692     _saveBreakpoints: function()
    693     {
    694         var breakpoints = [];
    695         for (var eventName in this._breakpointItems) {
    696             if (this._breakpointItems[eventName].checkbox.checked)
    697                 breakpoints.push({ eventName: eventName });
    698         }
    699         WebInspector.settings.eventListenerBreakpoints.set(breakpoints);
    700     },
    701 
    702     _restoreBreakpoints: function()
    703     {
    704         var breakpoints = WebInspector.settings.eventListenerBreakpoints.get();
    705         for (var i = 0; i < breakpoints.length; ++i) {
    706             var breakpoint = breakpoints[i];
    707             if (breakpoint && typeof breakpoint.eventName === "string")
    708                 this._setBreakpoint(breakpoint.eventName);
    709         }
    710     },
    711 
    712     __proto__: WebInspector.SidebarPane.prototype
    713 }
    714