2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
33 * @extends {WebInspector.SDKModel}
34 * @param {!WebInspector.Target} target
36 WebInspector.ConsoleModel = function(target)
38 WebInspector.SDKModel.call(this, WebInspector.ConsoleModel, target);
40 /** @type {!Array.<!WebInspector.ConsoleMessage>} */
44 this._consoleAgent = target.consoleAgent();
45 target.registerConsoleDispatcher(new WebInspector.ConsoleDispatcher(this));
49 WebInspector.ConsoleModel.Events = {
50 ConsoleCleared: "ConsoleCleared",
51 MessageAdded: "MessageAdded",
52 CommandEvaluated: "CommandEvaluated",
55 WebInspector.ConsoleModel.prototype = {
56 _enableAgent: function()
58 if (WebInspector.settings.monitoringXHREnabled.get())
59 this._consoleAgent.setMonitoringXHREnabled(true);
61 this._enablingConsole = true;
64 * @this {WebInspector.ConsoleModel}
68 delete this._enablingConsole;
70 this._consoleAgent.enable(callback.bind(this));
76 enablingConsole: function()
78 return !!this._enablingConsole;
82 * @param {!WebInspector.ConsoleMessage} msg
84 addMessage: function(msg)
86 if (WebInspector.NetworkManager.hasDevToolsRequestHeader(msg.request))
89 msg.index = this._messages.length;
90 this._messages.push(msg);
91 this._incrementErrorWarningCount(msg);
93 this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.MessageAdded, msg);
97 * @param {!WebInspector.ConsoleMessage} msg
99 _incrementErrorWarningCount: function(msg)
102 case WebInspector.ConsoleMessage.MessageLevel.Warning:
105 case WebInspector.ConsoleMessage.MessageLevel.Error:
112 * @return {!Array.<!WebInspector.ConsoleMessage>}
116 return this._messages;
119 requestClearMessages: function()
121 this._consoleAgent.clearMessages();
122 this._messagesCleared();
125 _messagesCleared: function()
130 this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.ConsoleCleared);
133 __proto__: WebInspector.SDKModel.prototype
137 * @param {!WebInspector.ExecutionContext} executionContext
138 * @param {string} text
139 * @param {boolean=} useCommandLineAPI
141 WebInspector.ConsoleModel.evaluateCommandInConsole = function(executionContext, text, useCommandLineAPI)
143 useCommandLineAPI = !!useCommandLineAPI;
144 var target = executionContext.target();
146 var commandMessage = new WebInspector.ConsoleMessage(target, WebInspector.ConsoleMessage.MessageSource.JS, null, text, WebInspector.ConsoleMessage.MessageType.Command);
147 commandMessage.setExecutionContextId(executionContext.id);
148 target.consoleModel.addMessage(commandMessage);
151 * @param {?WebInspector.RemoteObject} result
152 * @param {boolean} wasThrown
153 * @param {?RuntimeAgent.RemoteObject=} valueResult
154 * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
156 function printResult(result, wasThrown, valueResult, exceptionDetails)
161 WebInspector.console.showPromise().then(reportUponEvaluation).done();
162 function reportUponEvaluation()
164 target.consoleModel.dispatchEventToListeners(WebInspector.ConsoleModel.Events.CommandEvaluated, {result: result, wasThrown: wasThrown, text: text, commandMessage: commandMessage, exceptionDetails: exceptionDetails});
168 executionContext.evaluate(text, "console", useCommandLineAPI, false, false, true, printResult);
170 WebInspector.userMetrics.ConsoleEvaluated.record();
176 * @param {?WebInspector.Target} target
177 * @param {string} source
178 * @param {?string} level
179 * @param {string} messageText
180 * @param {string=} type
181 * @param {?string=} url
182 * @param {number=} line
183 * @param {number=} column
184 * @param {!NetworkAgent.RequestId=} requestId
185 * @param {!Array.<!RuntimeAgent.RemoteObject>=} parameters
186 * @param {!Array.<!ConsoleAgent.CallFrame>=} stackTrace
187 * @param {number=} timestamp
188 * @param {boolean=} isOutdated
189 * @param {!RuntimeAgent.ExecutionContextId=} executionContextId
190 * @param {!ConsoleAgent.AsyncStackTrace=} asyncStackTrace
191 * @param {?string=} scriptId
193 WebInspector.ConsoleMessage = function(target, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp, isOutdated, executionContextId, asyncStackTrace, scriptId)
195 this._target = target;
196 this.source = source;
198 this.messageText = messageText;
199 this.type = type || WebInspector.ConsoleMessage.MessageType.Log;
200 /** @type {string|undefined} */
201 this.url = url || undefined;
202 /** @type {number} */
203 this.line = line || 0;
204 /** @type {number} */
205 this.column = column || 0;
206 this.parameters = parameters;
207 /** @type {!Array.<!ConsoleAgent.CallFrame>|undefined} */
208 this.stackTrace = stackTrace;
209 this.timestamp = timestamp || Date.now();
210 this.isOutdated = isOutdated;
211 this.executionContextId = executionContextId || 0;
212 this.asyncStackTrace = asyncStackTrace;
213 this.scriptId = scriptId || null;
215 this.request = requestId ? target.networkLog.requestForId(requestId) : null;
218 var initiator = this.request.initiator();
220 this.stackTrace = initiator.stackTrace || undefined;
221 this.asyncStackTrace = initiator.asyncStackTrace;
223 this.url = initiator.url;
224 this.line = initiator.lineNumber || 0;
230 WebInspector.ConsoleMessage.prototype = {
232 * @return {?WebInspector.Target}
240 * @param {!WebInspector.ConsoleMessage} originatingMessage
242 setOriginatingMessage: function(originatingMessage)
244 this._originatingConsoleMessage = originatingMessage;
245 this.executionContextId = originatingMessage.executionContextId;
249 * @param {!RuntimeAgent.ExecutionContextId} executionContextId
251 setExecutionContextId: function(executionContextId)
253 this.executionContextId = executionContextId;
257 * @return {?WebInspector.ConsoleMessage}
259 originatingMessage: function()
261 return this._originatingConsoleMessage;
267 isGroupMessage: function()
269 return this.type === WebInspector.ConsoleMessage.MessageType.StartGroup ||
270 this.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed ||
271 this.type === WebInspector.ConsoleMessage.MessageType.EndGroup;
277 isGroupStartMessage: function()
279 return this.type === WebInspector.ConsoleMessage.MessageType.StartGroup ||
280 this.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed;
286 isErrorOrWarning: function()
288 return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error);
292 * @return {!WebInspector.ConsoleMessage}
296 return new WebInspector.ConsoleMessage(
305 this.request ? this.request.requestId : undefined,
310 this.executionContextId,
311 this.asyncStackTrace,
316 * @param {?WebInspector.ConsoleMessage} msg
319 isEqual: function(msg)
324 if (!this._isEqualStackTraces(this.stackTrace, msg.stackTrace))
327 var asyncTrace1 = this.asyncStackTrace;
328 var asyncTrace2 = msg.asyncStackTrace;
329 while (asyncTrace1 || asyncTrace2) {
330 if (!asyncTrace1 || !asyncTrace2)
332 if (asyncTrace1.description !== asyncTrace2.description)
334 if (!this._isEqualStackTraces(asyncTrace1.callFrames, asyncTrace2.callFrames))
336 asyncTrace1 = asyncTrace1.asyncStackTrace;
337 asyncTrace2 = asyncTrace2.asyncStackTrace;
340 if (this.parameters) {
341 if (!msg.parameters || this.parameters.length !== msg.parameters.length)
344 for (var i = 0; i < msg.parameters.length; ++i) {
345 // Never treat objects as equal - their properties might change over time.
346 if (this.parameters[i].type !== msg.parameters[i].type || msg.parameters[i].type === "object" || this.parameters[i].value !== msg.parameters[i].value)
351 return (this.target() === msg.target())
352 && (this.source === msg.source)
353 && (this.type === msg.type)
354 && (this.level === msg.level)
355 && (this.line === msg.line)
356 && (this.url === msg.url)
357 && (this.messageText === msg.messageText)
358 && (this.request === msg.request)
359 && (this.executionContextId === msg.executionContextId)
360 && (this.scriptId === msg.scriptId);
364 * @param {!Array.<!ConsoleAgent.CallFrame>|undefined} stackTrace1
365 * @param {!Array.<!ConsoleAgent.CallFrame>|undefined} stackTrace2
368 _isEqualStackTraces: function(stackTrace1, stackTrace2)
370 stackTrace1 = stackTrace1 || [];
371 stackTrace2 = stackTrace2 || [];
372 if (stackTrace1.length !== stackTrace2.length)
374 for (var i = 0, n = stackTrace1.length; i < n; ++i) {
375 if (stackTrace1[i].url !== stackTrace2[i].url ||
376 stackTrace1[i].functionName !== stackTrace2[i].functionName ||
377 stackTrace1[i].lineNumber !== stackTrace2[i].lineNumber ||
378 stackTrace1[i].columnNumber !== stackTrace2[i].columnNumber)
385 // Note: Keep these constants in sync with the ones in Console.h
389 WebInspector.ConsoleMessage.MessageSource = {
393 ConsoleAPI: "console-api",
395 AppCache: "appcache",
396 Rendering: "rendering",
398 Security: "security",
400 Deprecation: "deprecation"
406 WebInspector.ConsoleMessage.MessageType = {
413 StartGroup: "startGroup",
414 StartGroupCollapsed: "startGroupCollapsed",
415 EndGroup: "endGroup",
419 ProfileEnd: "profileEnd",
426 WebInspector.ConsoleMessage.MessageLevel = {
434 WebInspector.ConsoleMessage._messageLevelPriority = {
443 * @param {!WebInspector.ConsoleMessage} a
444 * @param {!WebInspector.ConsoleMessage} b
447 WebInspector.ConsoleMessage.messageLevelComparator = function(a, b)
449 return WebInspector.ConsoleMessage._messageLevelPriority[a.level] - WebInspector.ConsoleMessage._messageLevelPriority[b.level];
453 * @param {!WebInspector.ConsoleMessage} a
454 * @param {!WebInspector.ConsoleMessage} b
457 WebInspector.ConsoleMessage.timestampComparator = function (a, b)
459 return a.timestamp - b.timestamp;
464 * @implements {ConsoleAgent.Dispatcher}
465 * @param {!WebInspector.ConsoleModel} console
467 WebInspector.ConsoleDispatcher = function(console)
469 this._console = console;
472 WebInspector.ConsoleDispatcher.prototype = {
474 * @param {!ConsoleAgent.ConsoleMessage} payload
476 messageAdded: function(payload)
478 var consoleMessage = new WebInspector.ConsoleMessage(
479 this._console.target(),
487 payload.networkRequestId,
490 payload.timestamp * 1000, // Convert to ms.
491 this._console._enablingConsole,
492 payload.executionContextId,
493 payload.asyncStackTrace,
495 this._console.addMessage(consoleMessage);
499 * @param {number} count
501 messageRepeatCountUpdated: function(count)
505 messagesCleared: function()
507 if (!WebInspector.settings.preserveConsoleLog.get())
508 this._console._messagesCleared();
514 * @extends {WebInspector.Object}
515 * @implements {WebInspector.TargetManager.Observer}
517 WebInspector.MultitargetConsoleModel = function()
519 WebInspector.targetManager.observeTargets(this);
520 WebInspector.targetManager.addModelListener(WebInspector.ConsoleModel, WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this);
521 WebInspector.targetManager.addModelListener(WebInspector.ConsoleModel, WebInspector.ConsoleModel.Events.CommandEvaluated, this._commandEvaluated, this);
524 WebInspector.MultitargetConsoleModel.prototype = {
526 * @param {!WebInspector.Target} target
528 targetAdded: function(target)
530 if (!this._mainTarget) {
531 this._mainTarget = target;
532 target.consoleModel.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
537 * @param {!WebInspector.Target} target
539 targetRemoved: function(target)
541 if (this._mainTarget === target) {
542 delete this._mainTarget;
543 target.consoleModel.removeEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
548 * @return {!Array.<!WebInspector.ConsoleMessage>}
552 var targets = WebInspector.targetManager.targets();
554 for (var i = 0; i < targets.length; ++i)
555 result = result.concat(targets[i].consoleModel.messages());
559 _consoleCleared: function()
561 this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.ConsoleCleared);
565 * @param {!WebInspector.Event} event
567 _consoleMessageAdded: function(event)
569 this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.MessageAdded, event.data);
573 * @param {!WebInspector.Event} event
575 _commandEvaluated: function(event)
577 this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.CommandEvaluated, event.data);
580 __proto__: WebInspector.Object.prototype
584 * @type {!WebInspector.MultitargetConsoleModel}
586 WebInspector.multitargetConsoleModel;