Home | History | Annotate | Download | only in sdk
      1 /*
      2  * Copyright (C) 2012 Google 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 are
      6  * met:
      7  *
      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
     13  * distribution.
     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.
     17  *
     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.
     29  */
     30 
     31 /**
     32  * @constructor
     33  * @implements {WebInspector.TargetManager.Observer}
     34  * @param {!WebInspector.Workspace} workspace
     35  */
     36 WebInspector.PresentationConsoleMessageHelper = function(workspace)
     37 {
     38     /**
     39      * @type {!Object.<string, !Array.<!WebInspector.ConsoleMessage>>}
     40      */
     41     this._pendingConsoleMessages = {};
     42     this._presentationConsoleMessages = [];
     43     this._workspace = workspace;
     44 
     45     WebInspector.targetManager.observeTargets(this);
     46 }
     47 
     48 WebInspector.PresentationConsoleMessageHelper.prototype = {
     49     /**
     50      * @param {!WebInspector.Target} target
     51      */
     52     targetAdded: function(target)
     53     {
     54         target.consoleModel.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this);
     55         target.consoleModel.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
     56 
     57         target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
     58         target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._parsedScriptSource, this);
     59         target.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
     60     },
     61 
     62     /**
     63      * @param {!WebInspector.Target} target
     64      */
     65     targetRemoved: function(target)
     66     {
     67         target.consoleModel.removeEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this);
     68         target.consoleModel.removeEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
     69 
     70         target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
     71         target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._parsedScriptSource, this);
     72         target.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
     73     },
     74 
     75     /**
     76      * @param {!WebInspector.Event} event
     77      */
     78     _consoleMessageAdded: function(event)
     79     {
     80         var message = /** @type {!WebInspector.ConsoleMessage} */ (event.data);
     81         if (!message.url || !message.isErrorOrWarning())
     82             return;
     83 
     84         var rawLocation = this._rawLocation(message);
     85         if (rawLocation)
     86             this._addConsoleMessageToScript(message, rawLocation);
     87         else
     88             this._addPendingConsoleMessage(message);
     89     },
     90 
     91     /**
     92      * @param {!WebInspector.ConsoleMessage} message
     93      * @return {?WebInspector.DebuggerModel.Location}
     94      */
     95     _rawLocation: function(message)
     96     {
     97         // FIXME(62725): stack trace line/column numbers are one-based.
     98         var lineNumber = message.stackTrace ? message.stackTrace[0].lineNumber - 1 : message.line - 1;
     99         var columnNumber = message.stackTrace && message.stackTrace[0].columnNumber ? message.stackTrace[0].columnNumber - 1 : 0;
    100         return message.target().debuggerModel.createRawLocationByURL(message.url || "", lineNumber, columnNumber);
    101     },
    102 
    103     /**
    104      * @param {!WebInspector.ConsoleMessage} message
    105      * @param {!WebInspector.DebuggerModel.Location} rawLocation
    106      */
    107     _addConsoleMessageToScript: function(message, rawLocation)
    108     {
    109         this._presentationConsoleMessages.push(new WebInspector.PresentationConsoleMessage(message, rawLocation));
    110     },
    111 
    112     /**
    113      * @param {!WebInspector.ConsoleMessage} message
    114      */
    115     _addPendingConsoleMessage: function(message)
    116     {
    117         if (!message.url)
    118             return;
    119         if (!this._pendingConsoleMessages[message.url])
    120             this._pendingConsoleMessages[message.url] = [];
    121         this._pendingConsoleMessages[message.url].push(message);
    122     },
    123 
    124     /**
    125      * @param {!WebInspector.Event} event
    126      */
    127     _parsedScriptSource: function(event)
    128     {
    129         var script = /** @type {!WebInspector.Script} */ (event.data);
    130 
    131         var messages = this._pendingConsoleMessages[script.sourceURL];
    132         if (!messages)
    133             return;
    134 
    135         var pendingMessages = [];
    136         for (var i = 0; i < messages.length; i++) {
    137             var message = messages[i];
    138             var rawLocation = this._rawLocation(message);
    139             if (script.scriptId === rawLocation.scriptId)
    140                 this._addConsoleMessageToScript(message, rawLocation);
    141             else
    142                 pendingMessages.push(message);
    143         }
    144 
    145         if (pendingMessages.length)
    146             this._pendingConsoleMessages[script.sourceURL] = pendingMessages;
    147         else
    148             delete this._pendingConsoleMessages[script.sourceURL];
    149     },
    150 
    151     _consoleCleared: function()
    152     {
    153         this._pendingConsoleMessages = {};
    154         for (var i = 0; i < this._presentationConsoleMessages.length; ++i)
    155             this._presentationConsoleMessages[i].dispose();
    156         this._presentationConsoleMessages = [];
    157         var uiSourceCodes = this._workspace.uiSourceCodes();
    158         for (var i = 0; i < uiSourceCodes.length; ++i)
    159             uiSourceCodes[i].consoleMessagesCleared();
    160     },
    161 
    162     _debuggerReset: function()
    163     {
    164         this._pendingConsoleMessages = {};
    165         this._presentationConsoleMessages = [];
    166     }
    167 }
    168 
    169 /**
    170  * @constructor
    171  * @param {!WebInspector.ConsoleMessage} message
    172  * @param {!WebInspector.DebuggerModel.Location} rawLocation
    173  */
    174 WebInspector.PresentationConsoleMessage = function(message, rawLocation)
    175 {
    176     this.originalMessage = message;
    177     this._liveLocation = rawLocation.createLiveLocation(this._updateLocation.bind(this));
    178 }
    179 
    180 WebInspector.PresentationConsoleMessage.prototype = {
    181     /**
    182      * @param {!WebInspector.UILocation} uiLocation
    183      */
    184     _updateLocation: function(uiLocation)
    185     {
    186         if (this._uiLocation)
    187             this._uiLocation.uiSourceCode.consoleMessageRemoved(this);
    188         this._uiLocation = uiLocation;
    189         this._uiLocation.uiSourceCode.consoleMessageAdded(this);
    190     },
    191 
    192     get lineNumber()
    193     {
    194         return this._uiLocation.lineNumber;
    195     },
    196 
    197     dispose: function()
    198     {
    199         this._liveLocation.dispose();
    200     }
    201 }
    202