Update To 11.40.268.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      */
156     function printResult(result, wasThrown, valueResult, exceptionDetails)
157     {
158         if (!result)
159             return;
160
161         WebInspector.console.showPromise().then(reportUponEvaluation).done();
162         function reportUponEvaluation()
163         {
164             target.consoleModel.dispatchEventToListeners(WebInspector.ConsoleModel.Events.CommandEvaluated, {result: result, wasThrown: wasThrown, text: text, commandMessage: commandMessage, exceptionDetails: exceptionDetails});
165         }
166     }
167
168     executionContext.evaluate(text, "console", useCommandLineAPI, false, false, true, printResult);
169
170     WebInspector.userMetrics.ConsoleEvaluated.record();
171 }
172
173
174 /**
175  * @constructor
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
192  */
193 WebInspector.ConsoleMessage = function(target, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp, isOutdated, executionContextId, asyncStackTrace, scriptId)
194 {
195     this._target = target;
196     this.source = source;
197     this.level = level;
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;
214
215     this.request = requestId ? target.networkLog.requestForId(requestId) : null;
216
217     if (this.request) {
218         var initiator = this.request.initiator();
219         if (initiator) {
220             this.stackTrace = initiator.stackTrace || undefined;
221             this.asyncStackTrace = initiator.asyncStackTrace;
222             if (initiator.url) {
223                 this.url = initiator.url;
224                 this.line = initiator.lineNumber || 0;
225             }
226         }
227     }
228 }
229
230 WebInspector.ConsoleMessage.prototype = {
231     /**
232      * @return {?WebInspector.Target}
233      */
234     target: function()
235     {
236         return this._target;
237     },
238
239     /**
240      * @param {!WebInspector.ConsoleMessage} originatingMessage
241      */
242     setOriginatingMessage: function(originatingMessage)
243     {
244         this._originatingConsoleMessage = originatingMessage;
245         this.executionContextId = originatingMessage.executionContextId;
246     },
247
248     /**
249      * @param {!RuntimeAgent.ExecutionContextId} executionContextId
250      */
251     setExecutionContextId: function(executionContextId)
252     {
253         this.executionContextId = executionContextId;
254     },
255
256     /**
257      * @return {?WebInspector.ConsoleMessage}
258      */
259     originatingMessage: function()
260     {
261         return this._originatingConsoleMessage;
262     },
263
264     /**
265      * @return {boolean}
266      */
267     isGroupMessage: function()
268     {
269         return this.type === WebInspector.ConsoleMessage.MessageType.StartGroup ||
270             this.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed ||
271             this.type === WebInspector.ConsoleMessage.MessageType.EndGroup;
272     },
273
274     /**
275      * @return {boolean}
276      */
277     isGroupStartMessage: function()
278     {
279         return this.type === WebInspector.ConsoleMessage.MessageType.StartGroup ||
280             this.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed;
281     },
282
283     /**
284      * @return {boolean}
285      */
286     isErrorOrWarning: function()
287     {
288         return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error);
289     },
290
291     /**
292      * @return {!WebInspector.ConsoleMessage}
293      */
294     clone: function()
295     {
296         return new WebInspector.ConsoleMessage(
297             this.target(),
298             this.source,
299             this.level,
300             this.messageText,
301             this.type,
302             this.url,
303             this.line,
304             this.column,
305             this.request ? this.request.requestId : undefined,
306             this.parameters,
307             this.stackTrace,
308             this.timestamp,
309             this.isOutdated,
310             this.executionContextId,
311             this.asyncStackTrace,
312             this.scriptId);
313     },
314
315     /**
316      * @param {?WebInspector.ConsoleMessage} msg
317      * @return {boolean}
318      */
319     isEqual: function(msg)
320     {
321         if (!msg)
322             return false;
323
324         if (!this._isEqualStackTraces(this.stackTrace, msg.stackTrace))
325             return false;
326
327         var asyncTrace1 = this.asyncStackTrace;
328         var asyncTrace2 = msg.asyncStackTrace;
329         while (asyncTrace1 || asyncTrace2) {
330             if (!asyncTrace1 || !asyncTrace2)
331                 return false;
332             if (asyncTrace1.description !== asyncTrace2.description)
333                 return false;
334             if (!this._isEqualStackTraces(asyncTrace1.callFrames, asyncTrace2.callFrames))
335                 return false;
336             asyncTrace1 = asyncTrace1.asyncStackTrace;
337             asyncTrace2 = asyncTrace2.asyncStackTrace;
338         }
339
340         if (this.parameters) {
341             if (!msg.parameters || this.parameters.length !== msg.parameters.length)
342                 return false;
343
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)
347                     return false;
348             }
349         }
350
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);
361     },
362
363     /**
364      * @param {!Array.<!ConsoleAgent.CallFrame>|undefined} stackTrace1
365      * @param {!Array.<!ConsoleAgent.CallFrame>|undefined} stackTrace2
366      * @return {boolean}
367      */
368     _isEqualStackTraces: function(stackTrace1, stackTrace2)
369     {
370         stackTrace1 = stackTrace1 || [];
371         stackTrace2 = stackTrace2 || [];
372         if (stackTrace1.length !== stackTrace2.length)
373             return false;
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)
379                 return false;
380         }
381         return true;
382     }
383 }
384
385 // Note: Keep these constants in sync with the ones in Console.h
386 /**
387  * @enum {string}
388  */
389 WebInspector.ConsoleMessage.MessageSource = {
390     XML: "xml",
391     JS: "javascript",
392     Network: "network",
393     ConsoleAPI: "console-api",
394     Storage: "storage",
395     AppCache: "appcache",
396     Rendering: "rendering",
397     CSS: "css",
398     Security: "security",
399     Other: "other",
400     Deprecation: "deprecation"
401 }
402
403 /**
404  * @enum {string}
405  */
406 WebInspector.ConsoleMessage.MessageType = {
407     Log: "log",
408     Dir: "dir",
409     DirXML: "dirxml",
410     Table: "table",
411     Trace: "trace",
412     Clear: "clear",
413     StartGroup: "startGroup",
414     StartGroupCollapsed: "startGroupCollapsed",
415     EndGroup: "endGroup",
416     Assert: "assert",
417     Result: "result",
418     Profile: "profile",
419     ProfileEnd: "profileEnd",
420     Command: "command"
421 }
422
423 /**
424  * @enum {string}
425  */
426 WebInspector.ConsoleMessage.MessageLevel = {
427     Log: "log",
428     Info: "info",
429     Warning: "warning",
430     Error: "error",
431     Debug: "debug"
432 };
433
434 WebInspector.ConsoleMessage._messageLevelPriority = {
435     "debug": 0,
436     "log": 1,
437     "info": 2,
438     "warning": 3,
439     "error": 4
440 };
441
442 /**
443  * @param {!WebInspector.ConsoleMessage} a
444  * @param {!WebInspector.ConsoleMessage} b
445  * @return {number}
446  */
447 WebInspector.ConsoleMessage.messageLevelComparator = function(a, b)
448 {
449     return WebInspector.ConsoleMessage._messageLevelPriority[a.level] - WebInspector.ConsoleMessage._messageLevelPriority[b.level];
450 }
451
452 /**
453  * @param {!WebInspector.ConsoleMessage} a
454  * @param {!WebInspector.ConsoleMessage} b
455  * @return {number}
456  */
457 WebInspector.ConsoleMessage.timestampComparator = function (a, b)
458 {
459     return a.timestamp - b.timestamp;
460 }
461
462 /**
463  * @constructor
464  * @implements {ConsoleAgent.Dispatcher}
465  * @param {!WebInspector.ConsoleModel} console
466  */
467 WebInspector.ConsoleDispatcher = function(console)
468 {
469     this._console = console;
470 }
471
472 WebInspector.ConsoleDispatcher.prototype = {
473     /**
474      * @param {!ConsoleAgent.ConsoleMessage} payload
475      */
476     messageAdded: function(payload)
477     {
478         var consoleMessage = new WebInspector.ConsoleMessage(
479             this._console.target(),
480             payload.source,
481             payload.level,
482             payload.text,
483             payload.type,
484             payload.url,
485             payload.line,
486             payload.column,
487             payload.networkRequestId,
488             payload.parameters,
489             payload.stackTrace,
490             payload.timestamp * 1000, // Convert to ms.
491             this._console._enablingConsole,
492             payload.executionContextId,
493             payload.asyncStackTrace,
494             payload.scriptId);
495         this._console.addMessage(consoleMessage);
496     },
497
498     /**
499      * @param {number} count
500      */
501     messageRepeatCountUpdated: function(count)
502     {
503     },
504
505     messagesCleared: function()
506     {
507         if (!WebInspector.settings.preserveConsoleLog.get())
508             this._console._messagesCleared();
509     }
510 }
511
512 /**
513  * @constructor
514  * @extends {WebInspector.Object}
515  * @implements {WebInspector.TargetManager.Observer}
516  */
517 WebInspector.MultitargetConsoleModel = function()
518 {
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);
522 }
523
524 WebInspector.MultitargetConsoleModel.prototype = {
525     /**
526      * @param {!WebInspector.Target} target
527      */
528     targetAdded: function(target)
529     {
530         if (!this._mainTarget) {
531             this._mainTarget = target;
532             target.consoleModel.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
533         }
534     },
535
536     /**
537      * @param {!WebInspector.Target} target
538      */
539     targetRemoved: function(target)
540     {
541         if (this._mainTarget === target) {
542             delete this._mainTarget;
543             target.consoleModel.removeEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
544         }
545     },
546
547     /**
548      * @return {!Array.<!WebInspector.ConsoleMessage>}
549      */
550     messages: function()
551     {
552         var targets = WebInspector.targetManager.targets();
553         var result = [];
554         for (var i = 0; i < targets.length; ++i)
555             result = result.concat(targets[i].consoleModel.messages());
556         return result;
557     },
558
559     _consoleCleared: function()
560     {
561         this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.ConsoleCleared);
562     },
563
564     /**
565      * @param {!WebInspector.Event} event
566      */
567     _consoleMessageAdded: function(event)
568     {
569         this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.MessageAdded, event.data);
570     },
571
572     /**
573      * @param {!WebInspector.Event} event
574      */
575     _commandEvaluated: function(event)
576     {
577         this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.CommandEvaluated, event.data);
578     },
579
580     __proto__: WebInspector.Object.prototype
581 }
582
583 /**
584  * @type {!WebInspector.MultitargetConsoleModel}
585  */
586 WebInspector.multitargetConsoleModel;