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