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