• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
4  * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 
33 
34 #include "core/inspector/ConsoleMessage.h"
35 
36 #include "bindings/v8/ScriptCallStackFactory.h"
37 #include "bindings/v8/ScriptValue.h"
38 #include "core/inspector/IdentifiersFactory.h"
39 #include "core/inspector/InjectedScript.h"
40 #include "core/inspector/InjectedScriptManager.h"
41 #include "core/inspector/ScriptArguments.h"
42 #include "core/inspector/ScriptCallFrame.h"
43 #include "core/inspector/ScriptCallStack.h"
44 #include "wtf/CurrentTime.h"
45 
46 namespace WebCore {
47 
ConsoleMessage(bool canGenerateCallStack,MessageSource source,MessageType type,MessageLevel level,const String & message)48 ConsoleMessage::ConsoleMessage(bool canGenerateCallStack, MessageSource source, MessageType type, MessageLevel level, const String& message)
49     : m_source(source)
50     , m_type(type)
51     , m_level(level)
52     , m_message(message)
53     , m_url()
54     , m_line(0)
55     , m_column(0)
56     , m_repeatCount(1)
57     , m_requestId(IdentifiersFactory::requestId(0))
58     , m_timestamp(WTF::currentTime())
59 {
60     autogenerateMetadata(canGenerateCallStack);
61 }
62 
ConsoleMessage(bool canGenerateCallStack,MessageSource source,MessageType type,MessageLevel level,const String & message,const String & url,unsigned line,unsigned column,ScriptState * state,unsigned long requestIdentifier)63 ConsoleMessage::ConsoleMessage(bool canGenerateCallStack, MessageSource source, MessageType type, MessageLevel level, const String& message, const String& url, unsigned line, unsigned column, ScriptState* state, unsigned long requestIdentifier)
64     : m_source(source)
65     , m_type(type)
66     , m_level(level)
67     , m_message(message)
68     , m_url(url)
69     , m_line(line)
70     , m_column(column)
71     , m_repeatCount(1)
72     , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
73     , m_timestamp(WTF::currentTime())
74 {
75     autogenerateMetadata(canGenerateCallStack, state);
76 }
77 
ConsoleMessage(bool,MessageSource source,MessageType type,MessageLevel level,const String & message,PassRefPtr<ScriptCallStack> callStack,unsigned long requestIdentifier)78 ConsoleMessage::ConsoleMessage(bool, MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack, unsigned long requestIdentifier)
79     : m_source(source)
80     , m_type(type)
81     , m_level(level)
82     , m_message(message)
83     , m_arguments(0)
84     , m_line(0)
85     , m_column(0)
86     , m_repeatCount(1)
87     , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
88     , m_timestamp(WTF::currentTime())
89 {
90     if (callStack && callStack->size()) {
91         const ScriptCallFrame& frame = callStack->at(0);
92         m_url = frame.sourceURL();
93         m_line = frame.lineNumber();
94         m_column = frame.columnNumber();
95     }
96     m_callStack = callStack;
97 }
98 
ConsoleMessage(bool canGenerateCallStack,MessageSource source,MessageType type,MessageLevel level,const String & message,PassRefPtr<ScriptArguments> arguments,ScriptState * state,unsigned long requestIdentifier)99 ConsoleMessage::ConsoleMessage(bool canGenerateCallStack, MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptArguments> arguments, ScriptState* state, unsigned long requestIdentifier)
100     : m_source(source)
101     , m_type(type)
102     , m_level(level)
103     , m_message(message)
104     , m_arguments(arguments)
105     , m_url()
106     , m_line(0)
107     , m_column(0)
108     , m_repeatCount(1)
109     , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
110     , m_timestamp(WTF::currentTime())
111 {
112     autogenerateMetadata(canGenerateCallStack, state);
113 }
114 
~ConsoleMessage()115 ConsoleMessage::~ConsoleMessage()
116 {
117 }
118 
autogenerateMetadata(bool canGenerateCallStack,ScriptState * state)119 void ConsoleMessage::autogenerateMetadata(bool canGenerateCallStack, ScriptState* state)
120 {
121     if (m_type == EndGroupMessageType)
122         return;
123 
124     if (state)
125         m_callStack = createScriptCallStackForConsole();
126     else if (canGenerateCallStack)
127         m_callStack = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
128     else
129         return;
130 
131     if (m_callStack && m_callStack->size()) {
132         const ScriptCallFrame& frame = m_callStack->at(0);
133         m_url = frame.sourceURL();
134         m_line = frame.lineNumber();
135         m_column = frame.columnNumber();
136         return;
137     }
138 
139     m_callStack.clear();
140 }
141 
messageSourceValue(MessageSource source)142 static TypeBuilder::Console::ConsoleMessage::Source::Enum messageSourceValue(MessageSource source)
143 {
144     switch (source) {
145     case XMLMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Xml;
146     case JSMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Javascript;
147     case NetworkMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Network;
148     case ConsoleAPIMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Console_api;
149     case StorageMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Storage;
150     case AppCacheMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Appcache;
151     case RenderingMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Rendering;
152     case CSSMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Css;
153     case SecurityMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Security;
154     case OtherMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Other;
155     case DeprecationMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Deprecation;
156     }
157     return TypeBuilder::Console::ConsoleMessage::Source::Other;
158 }
159 
messageTypeValue(MessageType type)160 static TypeBuilder::Console::ConsoleMessage::Type::Enum messageTypeValue(MessageType type)
161 {
162     switch (type) {
163     case LogMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Log;
164     case ClearMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Clear;
165     case DirMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Dir;
166     case DirXMLMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Dirxml;
167     case TableMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Table;
168     case TraceMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Trace;
169     case StartGroupMessageType: return TypeBuilder::Console::ConsoleMessage::Type::StartGroup;
170     case StartGroupCollapsedMessageType: return TypeBuilder::Console::ConsoleMessage::Type::StartGroupCollapsed;
171     case EndGroupMessageType: return TypeBuilder::Console::ConsoleMessage::Type::EndGroup;
172     case AssertMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Assert;
173     }
174     return TypeBuilder::Console::ConsoleMessage::Type::Log;
175 }
176 
messageLevelValue(MessageLevel level)177 static TypeBuilder::Console::ConsoleMessage::Level::Enum messageLevelValue(MessageLevel level)
178 {
179     switch (level) {
180     case DebugMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Debug;
181     case LogMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Log;
182     case WarningMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Warning;
183     case ErrorMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Error;
184     case InfoMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Info;
185     }
186     return TypeBuilder::Console::ConsoleMessage::Level::Log;
187 }
188 
addToFrontend(InspectorFrontend::Console * frontend,InjectedScriptManager * injectedScriptManager,bool generatePreview)189 void ConsoleMessage::addToFrontend(InspectorFrontend::Console* frontend, InjectedScriptManager* injectedScriptManager, bool generatePreview)
190 {
191     RefPtr<TypeBuilder::Console::ConsoleMessage> jsonObj = TypeBuilder::Console::ConsoleMessage::create()
192         .setSource(messageSourceValue(m_source))
193         .setLevel(messageLevelValue(m_level))
194         .setText(m_message)
195         .setTimestamp(m_timestamp);
196     // FIXME: only send out type for ConsoleAPI source messages.
197     jsonObj->setType(messageTypeValue(m_type));
198     jsonObj->setLine(static_cast<int>(m_line));
199     jsonObj->setColumn(static_cast<int>(m_column));
200     jsonObj->setUrl(m_url);
201     jsonObj->setRepeatCount(static_cast<int>(m_repeatCount));
202     if (m_source == NetworkMessageSource && !m_requestId.isEmpty())
203         jsonObj->setNetworkRequestId(m_requestId);
204     if (m_arguments && m_arguments->argumentCount()) {
205         InjectedScript injectedScript = injectedScriptManager->injectedScriptFor(m_arguments->globalState());
206         if (!injectedScript.hasNoValue()) {
207             RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::RemoteObject> > jsonArgs = TypeBuilder::Array<TypeBuilder::Runtime::RemoteObject>::create();
208             if (m_type == TableMessageType && generatePreview && m_arguments->argumentCount()) {
209                 ScriptValue table = m_arguments->argumentAt(0);
210                 ScriptValue columns = m_arguments->argumentCount() > 1 ? m_arguments->argumentAt(1) : ScriptValue();
211                 RefPtr<TypeBuilder::Runtime::RemoteObject> inspectorValue = injectedScript.wrapTable(table, columns);
212                 if (!inspectorValue) {
213                     ASSERT_NOT_REACHED();
214                     return;
215                 }
216                 jsonArgs->addItem(inspectorValue);
217             } else {
218                 for (unsigned i = 0; i < m_arguments->argumentCount(); ++i) {
219                     RefPtr<TypeBuilder::Runtime::RemoteObject> inspectorValue = injectedScript.wrapObject(m_arguments->argumentAt(i), "console", generatePreview);
220                     if (!inspectorValue) {
221                         ASSERT_NOT_REACHED();
222                         return;
223                     }
224                     jsonArgs->addItem(inspectorValue);
225                 }
226             }
227             jsonObj->setParameters(jsonArgs);
228         }
229     }
230     if (m_callStack)
231         jsonObj->setStackTrace(m_callStack->buildInspectorArray());
232     frontend->messageAdded(jsonObj);
233 }
234 
incrementCount()235 void ConsoleMessage::incrementCount()
236 {
237     m_timestamp = WTF::currentTime();
238     ++m_repeatCount;
239 }
240 
updateRepeatCountInConsole(InspectorFrontend::Console * frontend)241 void ConsoleMessage::updateRepeatCountInConsole(InspectorFrontend::Console* frontend)
242 {
243     frontend->messageRepeatCountUpdated(m_repeatCount, m_timestamp);
244 }
245 
isEqual(ConsoleMessage * msg) const246 bool ConsoleMessage::isEqual(ConsoleMessage* msg) const
247 {
248     if (m_arguments) {
249         if (!m_arguments->isEqual(msg->m_arguments.get()))
250             return false;
251         // Never treat objects as equal - their properties might change over time.
252         for (size_t i = 0; i < m_arguments->argumentCount(); ++i) {
253             if (m_arguments->argumentAt(i).isObject())
254                 return false;
255         }
256     } else if (msg->m_arguments)
257         return false;
258 
259     if (m_callStack) {
260         if (!m_callStack->isEqual(msg->m_callStack.get()))
261             return false;
262     } else if (msg->m_callStack)
263         return false;
264 
265     return msg->m_source == m_source
266         && msg->m_type == m_type
267         && msg->m_level == m_level
268         && msg->m_message == m_message
269         && msg->m_line == m_line
270         && msg->m_column == m_column
271         && msg->m_url == m_url
272         && msg->m_requestId == m_requestId;
273 }
274 
windowCleared(DOMWindow * window)275 void ConsoleMessage::windowCleared(DOMWindow* window)
276 {
277     if (!m_arguments)
278         return;
279     if (m_arguments->globalState()->domWindow() != window)
280         return;
281     if (!m_message)
282         m_message = "<message collected>";
283     m_arguments.clear();
284 }
285 
argumentCount()286 unsigned ConsoleMessage::argumentCount()
287 {
288     if (m_arguments)
289         return m_arguments->argumentCount();
290     return 0;
291 }
292 
293 } // namespace WebCore
294 
295