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.Object}
34 */
35WebInspector.ConsoleModel = function()
36{
37    this.messages = [];
38    this.warnings = 0;
39    this.errors = 0;
40    this._interruptRepeatCount = false;
41    InspectorBackend.registerConsoleDispatcher(new WebInspector.ConsoleDispatcher(this));
42}
43
44WebInspector.ConsoleModel.Events = {
45    ConsoleCleared: "console-cleared",
46    MessageAdded: "console-message-added",
47    RepeatCountUpdated: "repeat-count-updated"
48}
49
50WebInspector.ConsoleModel.prototype = {
51    enableAgent: function()
52    {
53        if (WebInspector.settings.monitoringXHREnabled.get())
54            ConsoleAgent.setMonitoringXHREnabled(true);
55
56        this._enablingConsole = true;
57        function callback()
58        {
59            delete this._enablingConsole;
60        }
61        ConsoleAgent.enable(callback.bind(this));
62    },
63
64    /**
65     * @return {boolean}
66     */
67    enablingConsole: function()
68    {
69        return !!this._enablingConsole;
70    },
71
72    /**
73     * @param {WebInspector.ConsoleMessage} msg
74     */
75    addMessage: function(msg)
76    {
77        this.messages.push(msg);
78        this._previousMessage = msg;
79        this._incrementErrorWarningCount(msg);
80        this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.MessageAdded, msg);
81        this._interruptRepeatCount = false;
82    },
83
84    /**
85     * @param {WebInspector.ConsoleMessage} msg
86     */
87    _incrementErrorWarningCount: function(msg)
88    {
89        switch (msg.level) {
90            case WebInspector.ConsoleMessage.MessageLevel.Warning:
91                this.warnings += msg.repeatDelta;
92                break;
93            case WebInspector.ConsoleMessage.MessageLevel.Error:
94                this.errors += msg.repeatDelta;
95                break;
96        }
97    },
98
99    requestClearMessages: function()
100    {
101        ConsoleAgent.clearMessages();
102        this.clearMessages();
103    },
104
105    clearMessages: function()
106    {
107        this.messages = [];
108        delete this._previousMessage;
109
110        this.errors = 0;
111        this.warnings = 0;
112
113        this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.ConsoleCleared);
114    },
115
116    interruptRepeatCount: function()
117    {
118        this._interruptRepeatCount = true;
119    },
120
121    /**
122     * @param {number} count
123     */
124    _messageRepeatCountUpdated: function(count)
125    {
126        var msg = this._previousMessage;
127        if (!msg)
128            return;
129
130        var prevRepeatCount = msg.totalRepeatCount;
131
132        if (!this._interruptRepeatCount) {
133            msg.repeatDelta = count - prevRepeatCount;
134            msg.repeatCount = msg.repeatCount + msg.repeatDelta;
135            msg.totalRepeatCount = count;
136            msg.updateRepeatCount();
137
138            this._incrementErrorWarningCount(msg);
139            this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.RepeatCountUpdated, msg);
140        } else {
141            var msgCopy = msg.clone();
142            msgCopy.totalRepeatCount = count;
143            msgCopy.repeatCount = (count - prevRepeatCount) || 1;
144            msgCopy.repeatDelta = msgCopy.repeatCount;
145            this.addMessage(msgCopy);
146        }
147    },
148
149    __proto__: WebInspector.Object.prototype
150}
151
152/**
153 * @constructor
154 * @param {string} source
155 * @param {string} level
156 * @param {string=} url
157 * @param {number=} line
158 * @param {number=} repeatCount
159 */
160WebInspector.ConsoleMessage = function(source, level, url, line, repeatCount)
161{
162    this.source = source;
163    this.level = level;
164    this.url = url || null;
165    this.line = line || 0;
166    this.message = "";
167
168    repeatCount = repeatCount || 1;
169    this.repeatCount = repeatCount;
170    this.repeatDelta = repeatCount;
171    this.totalRepeatCount = repeatCount;
172}
173
174WebInspector.ConsoleMessage.prototype = {
175    /**
176     * @return {boolean}
177     */
178    isErrorOrWarning: function()
179    {
180        return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error);
181    },
182
183    updateRepeatCount: function()
184    {
185        // Implemented by concrete instances
186    },
187
188    /**
189     * @return {WebInspector.ConsoleMessage}
190     */
191    clone: function()
192    {
193        // Implemented by concrete instances
194    },
195
196    /**
197     * @return {WebInspector.DebuggerModel.Location}
198     */
199    location: function()
200    {
201        // Implemented by concrete instances
202    }
203}
204
205/**
206 * @param {string} source
207 * @param {string} level
208 * @param {string} message
209 * @param {string=} type
210 * @param {string=} url
211 * @param {number=} line
212 * @param {number=} repeatCount
213 * @param {Array.<RuntimeAgent.RemoteObject>=} parameters
214 * @param {ConsoleAgent.StackTrace=} stackTrace
215 * @param {NetworkAgent.RequestId=} requestId
216 * @param {boolean=} isOutdated
217 * @return {WebInspector.ConsoleMessage}
218 */
219WebInspector.ConsoleMessage.create = function(source, level, message, type, url, line, repeatCount, parameters, stackTrace, requestId, isOutdated)
220{
221}
222
223// Note: Keep these constants in sync with the ones in Console.h
224WebInspector.ConsoleMessage.MessageSource = {
225    XML: "xml",
226    JS: "javascript",
227    Network: "network",
228    ConsoleAPI: "console-api",
229    Storage: "storage",
230    AppCache: "appcache",
231    Rendering: "rendering",
232    CSS: "css",
233    Security: "security",
234    Other: "other"
235}
236
237WebInspector.ConsoleMessage.MessageType = {
238    Log: "log",
239    Dir: "dir",
240    DirXML: "dirxml",
241    Table: "table",
242    Trace: "trace",
243    Clear: "clear",
244    StartGroup: "startGroup",
245    StartGroupCollapsed: "startGroupCollapsed",
246    EndGroup: "endGroup",
247    Assert: "assert",
248    Result: "result",
249    Profile: "profile",
250    ProfileEnd: "profileEnd"
251}
252
253WebInspector.ConsoleMessage.MessageLevel = {
254    Log: "log",
255    Warning: "warning",
256    Error: "error",
257    Debug: "debug"
258}
259
260
261/**
262 * @constructor
263 * @implements {ConsoleAgent.Dispatcher}
264 * @param {WebInspector.ConsoleModel} console
265 */
266WebInspector.ConsoleDispatcher = function(console)
267{
268    this._console = console;
269}
270
271WebInspector.ConsoleDispatcher.prototype = {
272    /**
273     * @param {ConsoleAgent.ConsoleMessage} payload
274     */
275    messageAdded: function(payload)
276    {
277        var consoleMessage = WebInspector.ConsoleMessage.create(
278            payload.source,
279            payload.level,
280            payload.text,
281            payload.type,
282            payload.url,
283            payload.line,
284            payload.repeatCount,
285            payload.parameters,
286            payload.stackTrace,
287            payload.networkRequestId,
288            this._console._enablingConsole);
289        this._console.addMessage(consoleMessage);
290    },
291
292    /**
293     * @param {number} count
294     */
295    messageRepeatCountUpdated: function(count)
296    {
297        this._console._messageRepeatCountUpdated(count);
298    },
299
300    messagesCleared: function()
301    {
302        if (!WebInspector.settings.preserveConsoleLog.get())
303            this._console.clearMessages();
304    }
305}
306
307/**
308 * @type {?WebInspector.ConsoleModel}
309 */
310WebInspector.console = null;
311