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 * @param {WebInspector.UISourceCodeProvider} uiSourceCodeProvider
34 */
35WebInspector.PresentationConsoleMessageHelper = function(uiSourceCodeProvider)
36{
37    /**
38     * @type {Object.<string, Array.<WebInspector.ConsoleMessage>>}
39     */
40    this._pendingConsoleMessages = {};
41    this._presentationConsoleMessages = [];
42    this._uiSourceCodeProvider = uiSourceCodeProvider;
43
44    WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this);
45    WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.RepeatCountUpdated, this._consoleMessageAdded, this);
46    WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
47
48    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
49    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._parsedScriptSource, this);
50    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
51}
52
53WebInspector.PresentationConsoleMessageHelper.prototype = {
54    /**
55     * @param {WebInspector.Event} event
56     */
57    _consoleMessageAdded: function(event)
58    {
59        var message = /** @type {WebInspector.ConsoleMessage} */ (event.data);
60        if (!message.url || !message.isErrorOrWarning())
61            return;
62
63        var rawLocation = message.location();
64        if (rawLocation)
65            this._addConsoleMessageToScript(message, rawLocation);
66        else
67            this._addPendingConsoleMessage(message);
68    },
69
70    /**
71     * @param {WebInspector.ConsoleMessage} message
72     * @param {WebInspector.DebuggerModel.Location} rawLocation
73     */
74    _addConsoleMessageToScript: function(message, rawLocation)
75    {
76        this._presentationConsoleMessages.push(new WebInspector.PresentationConsoleMessage(message, rawLocation));
77    },
78
79    /**
80     * @param {WebInspector.ConsoleMessage} message
81     */
82    _addPendingConsoleMessage: function(message)
83    {
84        if (!message.url)
85            return;
86        if (!this._pendingConsoleMessages[message.url])
87            this._pendingConsoleMessages[message.url] = [];
88        this._pendingConsoleMessages[message.url].push(message);
89    },
90
91    /**
92     * @param {WebInspector.Event} event
93     */
94    _parsedScriptSource: function(event)
95    {
96        var script = /** @type {WebInspector.Script} */ (event.data);
97
98        var messages = this._pendingConsoleMessages[script.sourceURL];
99        if (!messages)
100            return;
101
102        var pendingMessages = [];
103        for (var i = 0; i < messages.length; i++) {
104            var message = messages[i];
105            var rawLocation = /** @type {WebInspector.DebuggerModel.Location} */ (message.location());
106            if (script.scriptId === rawLocation.scriptId)
107                this._addConsoleMessageToScript(message, rawLocation);
108            else
109                pendingMessages.push(message);
110        }
111
112        if (pendingMessages.length)
113            this._pendingConsoleMessages[script.sourceURL] = pendingMessages;
114        else
115            delete this._pendingConsoleMessages[script.sourceURL];
116    },
117
118    _consoleCleared: function()
119    {
120        this._pendingConsoleMessages = {};
121        for (var i = 0; i < this._presentationConsoleMessages.length; ++i)
122            this._presentationConsoleMessages[i].dispose();
123        this._presentationConsoleMessages = [];
124        var uiSourceCodes = this._uiSourceCodeProvider.uiSourceCodes();
125        for (var i = 0; i < uiSourceCodes.length; ++i)
126            uiSourceCodes[i].consoleMessagesCleared();
127    },
128
129    _debuggerReset: function()
130    {
131        this._pendingConsoleMessages = {};
132        this._presentationConsoleMessages = [];
133    }
134}
135
136/**
137 * @constructor
138 * @param {WebInspector.ConsoleMessage} message
139 * @param {WebInspector.DebuggerModel.Location} rawLocation
140 */
141WebInspector.PresentationConsoleMessage = function(message, rawLocation)
142{
143    this.originalMessage = message;
144    this._liveLocation = WebInspector.debuggerModel.createLiveLocation(rawLocation, this._updateLocation.bind(this));
145}
146
147WebInspector.PresentationConsoleMessage.prototype = {
148    /**
149     * @param {WebInspector.UILocation} uiLocation
150     */
151    _updateLocation: function(uiLocation)
152    {
153        if (this._uiLocation)
154            this._uiLocation.uiSourceCode.consoleMessageRemoved(this);
155        this._uiLocation = uiLocation;
156        this._uiLocation.uiSourceCode.consoleMessageAdded(this);
157    },
158
159    get lineNumber()
160    {
161        return this._uiLocation.lineNumber;
162    },
163
164    dispose: function()
165    {
166        this._liveLocation.dispose();
167    }
168}
169