Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / sdk / ConsoleModel.js
1 /*
2  * Copyright (C) 2011 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  * @extends {WebInspector.SDKModel}
34  * @param {!WebInspector.Target} target
35  */
36 WebInspector.ConsoleModel = function(target)
37 {
38     WebInspector.SDKModel.call(this, WebInspector.ConsoleModel, target);
39
40     /** @type {!Array.<!WebInspector.ConsoleMessage>} */
41     this._messages = [];
42     this.warnings = 0;
43     this.errors = 0;
44     this._consoleAgent = target.consoleAgent();
45     target.registerConsoleDispatcher(new WebInspector.ConsoleDispatcher(this));
46     this._enableAgent();
47 }
48
49 WebInspector.ConsoleModel.Events = {
50     ConsoleCleared: "ConsoleCleared",
51     MessageAdded: "MessageAdded",
52     CommandEvaluated: "CommandEvaluated",
53 }
54
55 WebInspector.ConsoleModel.prototype = {
56     _enableAgent: function()
57     {
58         if (WebInspector.settings.monitoringXHREnabled.get())
59             this._consoleAgent.setMonitoringXHREnabled(true);
60
61         this._enablingConsole = true;
62
63         /**
64          * @this {WebInspector.ConsoleModel}
65          */
66         function callback()
67         {
68             delete this._enablingConsole;
69         }
70         this._consoleAgent.enable(callback.bind(this));
71     },
72
73     /**
74      * @return {boolean}
75      */
76     enablingConsole: function()
77     {
78         return !!this._enablingConsole;
79     },
80
81     /**
82      * @param {!WebInspector.ConsoleMessage} msg
83      */
84     addMessage: function(msg)
85     {
86         if (WebInspector.NetworkManager.hasDevToolsRequestHeader(msg.request))
87             return;
88
89         msg.index = this._messages.length;
90         this._messages.push(msg);
91         this._incrementErrorWarningCount(msg);
92
93         this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.MessageAdded, msg);
94     },
95
96     /**
97      * @param {!WebInspector.ConsoleMessage} msg
98      */
99     _incrementErrorWarningCount: function(msg)
100     {
101         switch (msg.level) {
102             case WebInspector.ConsoleMessage.MessageLevel.Warning:
103                 this.warnings++;
104                 break;
105             case WebInspector.ConsoleMessage.MessageLevel.Error:
106                 this.errors++;
107                 break;
108         }
109     },
110
111     /**
112      * @return {!Array.<!WebInspector.ConsoleMessage>}
113      */
114     messages: function()
115     {
116         return this._messages;
117     },
118
119     requestClearMessages: function()
120     {
121         this._consoleAgent.clearMessages();
122         this._messagesCleared();
123     },
124
125     _messagesCleared: function()
126     {
127         this._messages = [];
128         this.errors = 0;
129         this.warnings = 0;
130         this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.ConsoleCleared);
131     },
132
133     __proto__: WebInspector.SDKModel.prototype
134 }
135
136 /**
137  * @param {!WebInspector.ExecutionContext} executionContext
138  * @param {string} text
139  * @param {boolean=} useCommandLineAPI
140  */
141 WebInspector.ConsoleModel.evaluateCommandInConsole = function(executionContext, text, useCommandLineAPI)
142 {
143     useCommandLineAPI = !!useCommandLineAPI;
144     var target = executionContext.target();
145
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);
149
150     /**
151      * @param {?WebInspector.RemoteObject} result
152      * @param {boolean} wasThrown
153      * @param {?RuntimeAgent.RemoteObject=} valueResult
154      * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
155      * @this {WebInspector.ConsoleModel}
156      */
157     function printResult(result, wasThrown, valueResult, exceptionDetails)
158     {
159         if (!result)
160             return;
161
162         WebInspector.console.show();
163         this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.CommandEvaluated, {result: result, wasThrown: wasThrown, text: text, commandMessage: commandMessage, exceptionDetails: exceptionDetails});
164     }
165
166     executionContext.evaluate(text, "console", useCommandLineAPI, false, false, true, printResult.bind(target.consoleModel));
167
168     WebInspector.userMetrics.ConsoleEvaluated.record();
169 }
170
171
172 /**
173  * @constructor
174  * @param {?WebInspector.Target} target
175  * @param {string} source
176  * @param {?string} level
177  * @param {string} messageText
178  * @param {string=} type
179  * @param {?string=} url
180  * @param {number=} line
181  * @param {number=} column
182  * @param {!NetworkAgent.RequestId=} requestId
183  * @param {!Array.<!RuntimeAgent.RemoteObject>=} parameters
184  * @param {!Array.<!ConsoleAgent.CallFrame>=} stackTrace
185  * @param {number=} timestamp
186  * @param {boolean=} isOutdated
187  * @param {!RuntimeAgent.ExecutionContextId=} executionContextId
188  * @param {!ConsoleAgent.AsyncStackTrace=} asyncStackTrace
189  * @param {?string=} scriptId
190  */
191 WebInspector.ConsoleMessage = function(target, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp, isOutdated, executionContextId, asyncStackTrace, scriptId)
192 {
193     this._target = target;
194     this.source = source;
195     this.level = level;
196     this.messageText = messageText;
197     this.type = type || WebInspector.ConsoleMessage.MessageType.Log;
198     /** @type {string|undefined} */
199     this.url = url || undefined;
200     /** @type {number} */
201     this.line = line || 0;
202     /** @type {number} */
203     this.column = column || 0;
204     this.parameters = parameters;
205     /** @type {!Array.<!ConsoleAgent.CallFrame>|undefined} */
206     this.stackTrace = stackTrace;
207     this.timestamp = timestamp || Date.now();
208     this.isOutdated = isOutdated;
209     this.executionContextId = executionContextId || 0;
210     this.asyncStackTrace = asyncStackTrace;
211     this.scriptId = scriptId || null;
212
213     this.request = requestId ? target.networkLog.requestForId(requestId) : null;
214
215     if (this.request) {
216         var initiator = this.request.initiator();
217         if (initiator) {
218             this.stackTrace = initiator.stackTrace || undefined;
219             this.asyncStackTrace = initiator.asyncStackTrace;
220             if (initiator.url) {
221                 this.url = initiator.url;
222                 this.line = initiator.lineNumber || 0;
223             }
224         }
225     }
226 }
227
228 WebInspector.ConsoleMessage.prototype = {
229     /**
230      * @return {?WebInspector.Target}
231      */
232     target: function()
233     {
234         return this._target;
235     },
236
237     /**
238      * @param {!WebInspector.ConsoleMessage} originatingMessage
239      */
240     setOriginatingMessage: function(originatingMessage)
241     {
242         this._originatingConsoleMessage = originatingMessage;
243         this.executionContextId = originatingMessage.executionContextId;
244     },
245
246     /**
247      * @param {!RuntimeAgent.ExecutionContextId} executionContextId
248      */
249     setExecutionContextId: function(executionContextId)
250     {
251         this.executionContextId = executionContextId;
252     },
253
254     /**
255      * @return {?WebInspector.ConsoleMessage}
256      */
257     originatingMessage: function()
258     {
259         return this._originatingConsoleMessage;
260     },
261
262     /**
263      * @return {boolean}
264      */
265     isGroupMessage: function()
266     {
267         return this.type === WebInspector.ConsoleMessage.MessageType.StartGroup ||
268             this.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed ||
269             this.type === WebInspector.ConsoleMessage.MessageType.EndGroup;
270     },
271
272     /**
273      * @return {boolean}
274      */
275     isGroupStartMessage: function()
276     {
277         return this.type === WebInspector.ConsoleMessage.MessageType.StartGroup ||
278             this.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed;
279     },
280
281     /**
282      * @return {boolean}
283      */
284     isErrorOrWarning: function()
285     {
286         return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error);
287     },
288
289     /**
290      * @return {!WebInspector.ConsoleMessage}
291      */
292     clone: function()
293     {
294         return new WebInspector.ConsoleMessage(
295             this.target(),
296             this.source,
297             this.level,
298             this.messageText,
299             this.type,
300             this.url,
301             this.line,
302             this.column,
303             this.request ? this.request.requestId : undefined,
304             this.parameters,
305             this.stackTrace,
306             this.timestamp,
307             this.isOutdated,
308             this.executionContextId,
309             this.asyncStackTrace,
310             this.scriptId);
311     },
312
313     /**
314      * @param {?WebInspector.ConsoleMessage} msg
315      * @return {boolean}
316      */
317     isEqual: function(msg)
318     {
319         if (!msg)
320             return false;
321
322         if (!this._isEqualStackTraces(this.stackTrace, msg.stackTrace))
323             return false;
324
325         var asyncTrace1 = this.asyncStackTrace;
326         var asyncTrace2 = msg.asyncStackTrace;
327         while (asyncTrace1 || asyncTrace2) {
328             if (!asyncTrace1 || !asyncTrace2)
329                 return false;
330             if (asyncTrace1.description !== asyncTrace2.description)
331                 return false;
332             if (!this._isEqualStackTraces(asyncTrace1.callFrames, asyncTrace2.callFrames))
333                 return false;
334             asyncTrace1 = asyncTrace1.asyncStackTrace;
335             asyncTrace2 = asyncTrace2.asyncStackTrace;
336         }
337
338         if (this.parameters) {
339             if (!msg.parameters || this.parameters.length !== msg.parameters.length)
340                 return false;
341
342             for (var i = 0; i < msg.parameters.length; ++i) {
343                 // Never treat objects as equal - their properties might change over time.
344                 if (this.parameters[i].type !== msg.parameters[i].type || msg.parameters[i].type === "object" || this.parameters[i].value !== msg.parameters[i].value)
345                     return false;
346             }
347         }
348
349         return (this.target() === msg.target())
350             && (this.source === msg.source)
351             && (this.type === msg.type)
352             && (this.level === msg.level)
353             && (this.line === msg.line)
354             && (this.url === msg.url)
355             && (this.messageText === msg.messageText)
356             && (this.request === msg.request)
357             && (this.executionContextId === msg.executionContextId)
358             && (this.scriptId === msg.scriptId);
359     },
360
361     /**
362      * @param {!Array.<!ConsoleAgent.CallFrame>|undefined} stackTrace1
363      * @param {!Array.<!ConsoleAgent.CallFrame>|undefined} stackTrace2
364      * @return {boolean}
365      */
366     _isEqualStackTraces: function(stackTrace1, stackTrace2)
367     {
368         stackTrace1 = stackTrace1 || [];
369         stackTrace2 = stackTrace2 || [];
370         if (stackTrace1.length !== stackTrace2.length)
371             return false;
372         for (var i = 0, n = stackTrace1.length; i < n; ++i) {
373             if (stackTrace1[i].url !== stackTrace2[i].url ||
374                 stackTrace1[i].functionName !== stackTrace2[i].functionName ||
375                 stackTrace1[i].lineNumber !== stackTrace2[i].lineNumber ||
376                 stackTrace1[i].columnNumber !== stackTrace2[i].columnNumber)
377                 return false;
378         }
379         return true;
380     }
381 }
382
383 // Note: Keep these constants in sync with the ones in Console.h
384 /**
385  * @enum {string}
386  */
387 WebInspector.ConsoleMessage.MessageSource = {
388     XML: "xml",
389     JS: "javascript",
390     Network: "network",
391     ConsoleAPI: "console-api",
392     Storage: "storage",
393     AppCache: "appcache",
394     Rendering: "rendering",
395     CSS: "css",
396     Security: "security",
397     Other: "other",
398     Deprecation: "deprecation"
399 }
400
401 /**
402  * @enum {string}
403  */
404 WebInspector.ConsoleMessage.MessageType = {
405     Log: "log",
406     Dir: "dir",
407     DirXML: "dirxml",
408     Table: "table",
409     Trace: "trace",
410     Clear: "clear",
411     StartGroup: "startGroup",
412     StartGroupCollapsed: "startGroupCollapsed",
413     EndGroup: "endGroup",
414     Assert: "assert",
415     Result: "result",
416     Profile: "profile",
417     ProfileEnd: "profileEnd",
418     Command: "command"
419 }
420
421 /**
422  * @enum {string}
423  */
424 WebInspector.ConsoleMessage.MessageLevel = {
425     Log: "log",
426     Info: "info",
427     Warning: "warning",
428     Error: "error",
429     Debug: "debug"
430 };
431
432 WebInspector.ConsoleMessage._messageLevelPriority = {
433     "debug": 0,
434     "log": 1,
435     "info": 2,
436     "warning": 3,
437     "error": 4
438 };
439
440 /**
441  * @param {!WebInspector.ConsoleMessage} a
442  * @param {!WebInspector.ConsoleMessage} b
443  * @return {number}
444  */
445 WebInspector.ConsoleMessage.messageLevelComparator = function(a, b)
446 {
447     return WebInspector.ConsoleMessage._messageLevelPriority[a.level] - WebInspector.ConsoleMessage._messageLevelPriority[b.level];
448 }
449
450 /**
451  * @param {!WebInspector.ConsoleMessage} a
452  * @param {!WebInspector.ConsoleMessage} b
453  * @return {number}
454  */
455 WebInspector.ConsoleMessage.timestampComparator = function (a, b)
456 {
457     return a.timestamp - b.timestamp;
458 }
459
460 /**
461  * @constructor
462  * @implements {ConsoleAgent.Dispatcher}
463  * @param {!WebInspector.ConsoleModel} console
464  */
465 WebInspector.ConsoleDispatcher = function(console)
466 {
467     this._console = console;
468 }
469
470 WebInspector.ConsoleDispatcher.prototype = {
471     /**
472      * @param {!ConsoleAgent.ConsoleMessage} payload
473      */
474     messageAdded: function(payload)
475     {
476         var consoleMessage = new WebInspector.ConsoleMessage(
477             this._console.target(),
478             payload.source,
479             payload.level,
480             payload.text,
481             payload.type,
482             payload.url,
483             payload.line,
484             payload.column,
485             payload.networkRequestId,
486             payload.parameters,
487             payload.stackTrace,
488             payload.timestamp * 1000, // Convert to ms.
489             this._console._enablingConsole,
490             payload.executionContextId,
491             payload.asyncStackTrace,
492             payload.scriptId);
493         this._console.addMessage(consoleMessage);
494     },
495
496     /**
497      * @param {number} count
498      */
499     messageRepeatCountUpdated: function(count)
500     {
501     },
502
503     messagesCleared: function()
504     {
505         if (!WebInspector.settings.preserveConsoleLog.get())
506             this._console._messagesCleared();
507     }
508 }
509
510 /**
511  * @constructor
512  * @extends {WebInspector.Object}
513  * @implements {WebInspector.TargetManager.Observer}
514  */
515 WebInspector.MultitargetConsoleModel = function()
516 {
517     WebInspector.targetManager.observeTargets(this);
518     WebInspector.targetManager.addModelListener(WebInspector.ConsoleModel, WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this);
519     WebInspector.targetManager.addModelListener(WebInspector.ConsoleModel, WebInspector.ConsoleModel.Events.CommandEvaluated, this._commandEvaluated, this);
520 }
521
522 WebInspector.MultitargetConsoleModel.prototype = {
523     /**
524      * @param {!WebInspector.Target} target
525      */
526     targetAdded: function(target)
527     {
528         if (!this._mainTarget) {
529             this._mainTarget = target;
530             target.consoleModel.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
531         }
532     },
533
534     /**
535      * @param {!WebInspector.Target} target
536      */
537     targetRemoved: function(target)
538     {
539         if (this._mainTarget === target) {
540             delete this._mainTarget;
541             target.consoleModel.removeEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
542         }
543     },
544
545     /**
546      * @return {!Array.<!WebInspector.ConsoleMessage>}
547      */
548     messages: function()
549     {
550         var targets = WebInspector.targetManager.targets();
551         var result = [];
552         for (var i = 0; i < targets.length; ++i)
553             result = result.concat(targets[i].consoleModel.messages());
554         return result;
555     },
556
557     _consoleCleared: function()
558     {
559         this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.ConsoleCleared);
560     },
561
562     /**
563      * @param {!WebInspector.Event} event
564      */
565     _consoleMessageAdded: function(event)
566     {
567         this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.MessageAdded, event.data);
568     },
569
570     /**
571      * @param {!WebInspector.Event} event
572      */
573     _commandEvaluated: function(event)
574     {
575         this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.CommandEvaluated, event.data);
576     },
577
578     __proto__: WebInspector.Object.prototype
579 }
580
581 /**
582  * @type {!WebInspector.MultitargetConsoleModel}
583  */
584 WebInspector.multitargetConsoleModel;