Remove ENABLE(INSPECTOR) ifdef guards
[WebKit-https.git] / Source / JavaScriptCore / inspector / ConsoleMessage.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2014 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 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 #include "ConsoleMessage.h"
33
34 #include "IdentifiersFactory.h"
35 #include "InjectedScript.h"
36 #include "InjectedScriptManager.h"
37 #include "InspectorValues.h"
38 #include "ScriptArguments.h"
39 #include "ScriptCallFrame.h"
40 #include "ScriptCallStack.h"
41 #include "ScriptCallStackFactory.h"
42 #include "ScriptValue.h"
43
44 namespace Inspector {
45
46 ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned long requestIdentifier)
47     : m_source(source)
48     , m_type(type)
49     , m_level(level)
50     , m_message(message)
51     , m_url()
52     , m_line(0)
53     , m_column(0)
54     , m_repeatCount(1)
55     , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
56 {
57 }
58
59 ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, const String& url, unsigned line, unsigned column, JSC::ExecState* state, unsigned long requestIdentifier)
60     : m_source(source)
61     , m_type(type)
62     , m_level(level)
63     , m_message(message)
64     , m_url(url)
65     , m_line(line)
66     , m_column(column)
67     , m_repeatCount(1)
68     , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
69 {
70     autogenerateMetadata(state);
71 }
72
73 ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack, unsigned long requestIdentifier)
74     : m_source(source)
75     , m_type(type)
76     , m_level(level)
77     , m_message(message)
78     , m_url()
79     , m_line(0)
80     , m_column(0)
81     , m_repeatCount(1)
82     , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
83 {
84     m_callStack = callStack;
85
86     const ScriptCallFrame* frame = m_callStack ? m_callStack->firstNonNativeCallFrame() : nullptr;
87     if (frame) {
88         m_url = frame->sourceURL();
89         m_line = frame->lineNumber();
90         m_column = frame->columnNumber();
91     }
92 }
93
94 ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptArguments> arguments, JSC::ExecState* state, unsigned long requestIdentifier)
95     : m_source(source)
96     , m_type(type)
97     , m_level(level)
98     , m_message(message)
99     , m_arguments(arguments)
100     , m_url()
101     , m_line(0)
102     , m_column(0)
103     , m_repeatCount(1)
104     , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
105 {
106     autogenerateMetadata(state);
107 }
108
109 ConsoleMessage::~ConsoleMessage()
110 {
111 }
112
113 void ConsoleMessage::autogenerateMetadata(JSC::ExecState* state)
114 {
115     if (!state)
116         return;
117
118     if (m_type == MessageType::EndGroup)
119         return;
120
121     // FIXME: Should this really be using "for console" in the generic ConsoleMessage autogeneration? This can skip the first frame.
122     m_callStack = createScriptCallStackForConsole(state, ScriptCallStack::maxCallStackSizeToCapture);
123
124     if (const ScriptCallFrame* frame = m_callStack->firstNonNativeCallFrame()) {
125         m_url = frame->sourceURL();
126         m_line = frame->lineNumber();
127         m_column = frame->columnNumber();
128         return;
129     }
130 }
131
132 static Inspector::Protocol::Console::ConsoleMessage::Source messageSourceValue(MessageSource source)
133 {
134     switch (source) {
135     case MessageSource::XML: return Inspector::Protocol::Console::ConsoleMessage::Source::XML;
136     case MessageSource::JS: return Inspector::Protocol::Console::ConsoleMessage::Source::Javascript;
137     case MessageSource::Network: return Inspector::Protocol::Console::ConsoleMessage::Source::Network;
138     case MessageSource::ConsoleAPI: return Inspector::Protocol::Console::ConsoleMessage::Source::ConsoleAPI;
139     case MessageSource::Storage: return Inspector::Protocol::Console::ConsoleMessage::Source::Storage;
140     case MessageSource::AppCache: return Inspector::Protocol::Console::ConsoleMessage::Source::Appcache;
141     case MessageSource::Rendering: return Inspector::Protocol::Console::ConsoleMessage::Source::Rendering;
142     case MessageSource::CSS: return Inspector::Protocol::Console::ConsoleMessage::Source::CSS;
143     case MessageSource::Security: return Inspector::Protocol::Console::ConsoleMessage::Source::Security;
144     case MessageSource::Other: return Inspector::Protocol::Console::ConsoleMessage::Source::Other;
145     }
146     return Inspector::Protocol::Console::ConsoleMessage::Source::Other;
147 }
148
149 static Inspector::Protocol::Console::ConsoleMessage::Type messageTypeValue(MessageType type)
150 {
151     switch (type) {
152     case MessageType::Log: return Inspector::Protocol::Console::ConsoleMessage::Type::Log;
153     case MessageType::Clear: return Inspector::Protocol::Console::ConsoleMessage::Type::Clear;
154     case MessageType::Dir: return Inspector::Protocol::Console::ConsoleMessage::Type::Dir;
155     case MessageType::DirXML: return Inspector::Protocol::Console::ConsoleMessage::Type::DirXML;
156     case MessageType::Table: return Inspector::Protocol::Console::ConsoleMessage::Type::Table;
157     case MessageType::Trace: return Inspector::Protocol::Console::ConsoleMessage::Type::Trace;
158     case MessageType::StartGroup: return Inspector::Protocol::Console::ConsoleMessage::Type::StartGroup;
159     case MessageType::StartGroupCollapsed: return Inspector::Protocol::Console::ConsoleMessage::Type::StartGroupCollapsed;
160     case MessageType::EndGroup: return Inspector::Protocol::Console::ConsoleMessage::Type::EndGroup;
161     case MessageType::Assert: return Inspector::Protocol::Console::ConsoleMessage::Type::Assert;
162     case MessageType::Timing: return Inspector::Protocol::Console::ConsoleMessage::Type::Timing;
163     case MessageType::Profile: return Inspector::Protocol::Console::ConsoleMessage::Type::Profile;
164     case MessageType::ProfileEnd: return Inspector::Protocol::Console::ConsoleMessage::Type::ProfileEnd;
165     }
166     return Inspector::Protocol::Console::ConsoleMessage::Type::Log;
167 }
168
169 static Inspector::Protocol::Console::ConsoleMessage::Level messageLevelValue(MessageLevel level)
170 {
171     switch (level) {
172     case MessageLevel::Log: return Inspector::Protocol::Console::ConsoleMessage::Level::Log;
173     case MessageLevel::Warning: return Inspector::Protocol::Console::ConsoleMessage::Level::Warning;
174     case MessageLevel::Error: return Inspector::Protocol::Console::ConsoleMessage::Level::Error;
175     case MessageLevel::Debug: return Inspector::Protocol::Console::ConsoleMessage::Level::Debug;
176     }
177     return Inspector::Protocol::Console::ConsoleMessage::Level::Log;
178 }
179
180 void ConsoleMessage::addToFrontend(InspectorConsoleFrontendDispatcher* consoleFrontendDispatcher, Inspector::InjectedScriptManager* injectedScriptManager, bool generatePreview)
181 {
182     Ref<Inspector::Protocol::Console::ConsoleMessage> jsonObj = Inspector::Protocol::Console::ConsoleMessage::create()
183         .setSource(messageSourceValue(m_source))
184         .setLevel(messageLevelValue(m_level))
185         .setText(m_message)
186         .release();
187
188     // FIXME: only send out type for ConsoleAPI source messages.
189     jsonObj->setType(messageTypeValue(m_type));
190     jsonObj->setLine(static_cast<int>(m_line));
191     jsonObj->setColumn(static_cast<int>(m_column));
192     jsonObj->setUrl(m_url);
193     jsonObj->setRepeatCount(static_cast<int>(m_repeatCount));
194
195     if (m_source == MessageSource::Network && !m_requestId.isEmpty())
196         jsonObj->setNetworkRequestId(m_requestId);
197
198     if (m_arguments && m_arguments->argumentCount()) {
199         InjectedScript injectedScript = injectedScriptManager->injectedScriptFor(m_arguments->globalState());
200         if (!injectedScript.hasNoValue()) {
201             Ref<Inspector::Protocol::Array<Inspector::Protocol::Runtime::RemoteObject>> jsonArgs = Inspector::Protocol::Array<Inspector::Protocol::Runtime::RemoteObject>::create();
202             if (m_type == MessageType::Table && generatePreview && m_arguments->argumentCount()) {
203                 Deprecated::ScriptValue table = m_arguments->argumentAt(0);
204                 Deprecated::ScriptValue columns = m_arguments->argumentCount() > 1 ? m_arguments->argumentAt(1) : Deprecated::ScriptValue();
205                 RefPtr<Inspector::Protocol::Runtime::RemoteObject> inspectorValue = injectedScript.wrapTable(table, columns);
206                 if (!inspectorValue) {
207                     ASSERT_NOT_REACHED();
208                     return;
209                 }
210                 jsonArgs->addItem(inspectorValue.copyRef());
211             } else {
212                 for (unsigned i = 0; i < m_arguments->argumentCount(); ++i) {
213                     RefPtr<Inspector::Protocol::Runtime::RemoteObject> inspectorValue = injectedScript.wrapObject(m_arguments->argumentAt(i), ASCIILiteral("console"), generatePreview);
214                     if (!inspectorValue) {
215                         ASSERT_NOT_REACHED();
216                         return;
217                     }
218                     jsonArgs->addItem(inspectorValue.copyRef());
219                 }
220             }
221             jsonObj->setParameters(WTF::move(jsonArgs));
222         }
223     }
224
225     if (m_callStack)
226         jsonObj->setStackTrace(m_callStack->buildInspectorArray());
227
228     consoleFrontendDispatcher->messageAdded(WTF::move(jsonObj));
229 }
230
231 void ConsoleMessage::updateRepeatCountInConsole(InspectorConsoleFrontendDispatcher* consoleFrontendDispatcher)
232 {
233     consoleFrontendDispatcher->messageRepeatCountUpdated(m_repeatCount);
234 }
235
236 bool ConsoleMessage::isEqual(ConsoleMessage* msg) const
237 {
238     if (m_arguments) {
239         if (!m_arguments->isEqual(msg->m_arguments.get()))
240             return false;
241
242         // Never treat objects as equal - their properties might change over time.
243         for (size_t i = 0; i < m_arguments->argumentCount(); ++i) {
244             if (m_arguments->argumentAt(i).isObject())
245                 return false;
246         }
247     } else if (msg->m_arguments)
248         return false;
249
250     if (m_callStack) {
251         if (!m_callStack->isEqual(msg->m_callStack.get()))
252             return false;
253     } else if (msg->m_callStack)
254         return false;
255
256     return msg->m_source == m_source
257         && msg->m_type == m_type
258         && msg->m_level == m_level
259         && msg->m_message == m_message
260         && msg->m_line == m_line
261         && msg->m_column == m_column
262         && msg->m_url == m_url
263         && msg->m_requestId == m_requestId;
264 }
265
266 void ConsoleMessage::clear()
267 {
268     if (!m_message)
269         m_message = ASCIILiteral("<message collected>");
270
271     if (m_arguments)
272         m_arguments.clear();
273 }
274
275 JSC::ExecState* ConsoleMessage::scriptState() const
276 {
277     if (m_arguments)
278         return m_arguments->globalState();
279
280     return nullptr;
281 }
282
283 unsigned ConsoleMessage::argumentCount() const
284 {
285     if (m_arguments)
286         return m_arguments->argumentCount();
287
288     return 0;
289 }
290
291 } // namespace Inspector